LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme.c (source / functions) Hit Total Coverage
Test: Combined Lines: 773 871 88.7 %
Date: 2024-12-13 15:12:43 Functions: 49 50 98.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1513 2538 59.6 %

           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                 :       5138 : nvme_ctrlr_shared(const struct spdk_nvme_ctrlr *ctrlr)
      28                 :            : {
      29   [ +  -  +  -  :       5138 :         return ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE;
                   +  - ]
      30                 :            : }
      31                 :            : 
      32                 :            : void
      33                 :         37 : nvme_ctrlr_connected(struct spdk_nvme_probe_ctx *probe_ctx,
      34                 :            :                      struct spdk_nvme_ctrlr *ctrlr)
      35                 :            : {
      36   [ #  #  #  #  :         37 :         TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
      37                 :         37 : }
      38                 :            : 
      39                 :            : static void
      40                 :       2591 : nvme_ctrlr_detach_async_finish(struct spdk_nvme_ctrlr *ctrlr)
      41                 :            : {
      42         [ +  - ]:       2591 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
      43         [ +  + ]:       2591 :         if (nvme_ctrlr_shared(ctrlr)) {
      44   [ +  +  +  -  :        694 :                 TAILQ_REMOVE(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
      45                 :         10 :         } else {
      46   [ +  +  +  -  :       1897 :                 TAILQ_REMOVE(&g_nvme_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
      47                 :            :         }
      48         [ +  - ]:       2591 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
      49                 :       2591 : }
      50                 :            : 
      51                 :            : static int
      52                 :       2822 : nvme_ctrlr_detach_async(struct spdk_nvme_ctrlr *ctrlr,
      53                 :            :                         struct nvme_ctrlr_detach_ctx **_ctx)
      54                 :            : {
      55                 :         11 :         struct nvme_ctrlr_detach_ctx *ctx;
      56                 :         11 :         int ref_count;
      57                 :            : 
      58         [ +  - ]:       2822 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
      59                 :            : 
      60                 :       2822 :         ref_count = nvme_ctrlr_get_ref_count(ctrlr);
      61   [ +  +  #  # ]:       2822 :         assert(ref_count > 0);
      62                 :            : 
      63         [ +  + ]:       2822 :         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                 :       2591 :                 ctx = calloc(1, sizeof(*ctx));
      68         [ +  + ]:       2591 :                 if (ctx == NULL) {
      69         [ #  # ]:          0 :                         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
      70                 :            : 
      71                 :          0 :                         return -ENOMEM;
      72                 :            :                 }
      73   [ +  -  +  - ]:       2591 :                 ctx->ctrlr = ctrlr;
      74   [ +  -  +  - ]:       2591 :                 ctx->cb_fn = nvme_ctrlr_detach_async_finish;
      75                 :            : 
      76                 :       2591 :                 nvme_ctrlr_proc_put_ref(ctrlr);
      77                 :            : 
      78                 :       2591 :                 nvme_io_msg_ctrlr_detach(ctrlr);
      79                 :            : 
      80                 :       2591 :                 nvme_ctrlr_destruct_async(ctrlr, ctx);
      81                 :            : 
      82         [ +  - ]:       2591 :                 *_ctx = ctx;
      83                 :       1070 :         } else {
      84                 :        231 :                 nvme_ctrlr_proc_put_ref(ctrlr);
      85                 :            :         }
      86                 :            : 
      87         [ +  - ]:       2822 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
      88                 :            : 
      89                 :       2822 :         return 0;
      90                 :       1071 : }
      91                 :            : 
      92                 :            : static int
      93                 :   19606322 : nvme_ctrlr_detach_poll_async(struct nvme_ctrlr_detach_ctx *ctx)
      94                 :            : {
      95                 :         11 :         int rc;
      96                 :            : 
      97   [ +  -  +  - ]:   19606322 :         rc = nvme_ctrlr_destruct_poll_async(ctx->ctrlr, ctx);
      98         [ +  + ]:   19606322 :         if (rc == -EAGAIN) {
      99                 :   19603731 :                 return -EAGAIN;
     100                 :            :         }
     101                 :            : 
     102                 :       2591 :         free(ctx);
     103                 :            : 
     104                 :       2591 :         return rc;
     105                 :    1249889 : }
     106                 :            : 
     107                 :            : int
     108                 :        426 : spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
     109                 :            : {
     110                 :        426 :         struct nvme_ctrlr_detach_ctx *ctx = NULL;
     111                 :          5 :         int rc;
     112                 :            : 
     113                 :        426 :         rc = nvme_ctrlr_detach_async(ctrlr, &ctx);
     114         [ -  + ]:        426 :         if (rc != 0) {
     115                 :          0 :                 return rc;
     116         [ +  + ]:        426 :         } else if (ctx == NULL) {
     117                 :            :                 /* ctrlr was detached from the caller process but any other process
     118                 :            :                  * still attaches it.
     119                 :            :                  */
     120                 :          6 :                 return 0;
     121                 :            :         }
     122                 :            : 
     123                 :         39 :         while (1) {
     124                 :       2981 :                 rc = nvme_ctrlr_detach_poll_async(ctx);
     125         [ +  + ]:       2981 :                 if (rc != -EAGAIN) {
     126                 :        420 :                         break;
     127                 :            :                 }
     128                 :       2561 :                 nvme_delay(1000);
     129                 :            :         }
     130                 :            : 
     131                 :        420 :         return 0;
     132                 :         12 : }
     133                 :            : 
     134                 :            : int
     135                 :       2396 : spdk_nvme_detach_async(struct spdk_nvme_ctrlr *ctrlr,
     136                 :            :                        struct spdk_nvme_detach_ctx **_detach_ctx)
     137                 :            : {
     138                 :          6 :         struct spdk_nvme_detach_ctx *detach_ctx;
     139                 :       2396 :         struct nvme_ctrlr_detach_ctx *ctx = NULL;
     140                 :          6 :         int rc;
     141                 :            : 
     142   [ +  -  -  + ]:       2396 :         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         [ +  - ]:       2396 :         detach_ctx = *_detach_ctx;
     150         [ +  + ]:       2396 :         if (detach_ctx == NULL) {
     151                 :       2363 :                 detach_ctx = calloc(1, sizeof(*detach_ctx));
     152         [ +  + ]:       2363 :                 if (detach_ctx == NULL) {
     153                 :          0 :                         return -ENOMEM;
     154                 :            :                 }
     155   [ +  -  +  -  :       2363 :                 TAILQ_INIT(&detach_ctx->head);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     156                 :       1056 :         }
     157                 :            : 
     158                 :       2396 :         rc = nvme_ctrlr_detach_async(ctrlr, &ctx);
     159   [ +  -  +  + ]:       2396 :         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   [ +  -  +  -  :       2171 :         TAILQ_INSERT_TAIL(&detach_ctx->head, ctx, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     171                 :            : 
     172         [ +  - ]:       2171 :         *_detach_ctx = detach_ctx;
     173                 :            : 
     174                 :       2171 :         return 0;
     175                 :       1059 : }
     176                 :            : 
     177                 :            : int
     178                 :   19603248 : spdk_nvme_detach_poll_async(struct spdk_nvme_detach_ctx *detach_ctx)
     179                 :            : {
     180                 :          4 :         struct nvme_ctrlr_detach_ctx *ctx, *tmp_ctx;
     181                 :          4 :         int rc;
     182                 :            : 
     183         [ +  + ]:   19603248 :         if (detach_ctx == NULL) {
     184                 :          0 :                 return -EINVAL;
     185                 :            :         }
     186                 :            : 
     187   [ +  +  +  -  :   39206589 :         TAILQ_FOREACH_SAFE(ctx, &detach_ctx->head, link, tmp_ctx) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
     188   [ +  +  +  -  :   19603341 :                 TAILQ_REMOVE(&detach_ctx->head, ctx, link);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     189                 :            : 
     190                 :   19603341 :                 rc = nvme_ctrlr_detach_poll_async(ctx);
     191         [ +  + ]:   19603341 :                 if (rc == -EAGAIN) {
     192                 :            :                         /* If not -EAGAIN, ctx was freed by nvme_ctrlr_detach_poll_async(). */
     193   [ +  +  +  -  :   19601170 :                         TAILQ_INSERT_HEAD(&detach_ctx->head, ctx, link);
          +  -  +  -  +  
          -  +  -  -  +  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     194                 :    1248791 :                 }
     195                 :    1249850 :         }
     196                 :            : 
     197   [ +  +  +  -  :   19603248 :         if (!TAILQ_EMPTY(&detach_ctx->head)) {
             +  -  +  + ]
     198                 :   19601110 :                 return -EAGAIN;
     199                 :            :         }
     200                 :            : 
     201                 :       2138 :         free(detach_ctx);
     202                 :       2138 :         return 0;
     203                 :    1249847 : }
     204                 :            : 
     205                 :            : void
     206                 :       1297 : spdk_nvme_detach_poll(struct spdk_nvme_detach_ctx *detach_ctx)
     207                 :            : {
     208   [ +  +  +  + ]:   19418547 :         while (detach_ctx && spdk_nvme_detach_poll_async(detach_ctx) == -EAGAIN) {
     209                 :            :                 ;
     210                 :            :         }
     211                 :       1297 : }
     212                 :            : 
     213                 :            : void
     214                 :      12075 : nvme_completion_poll_cb(void *arg, const struct spdk_nvme_cpl *cpl)
     215                 :            : {
     216                 :      12075 :         struct nvme_completion_poll_status      *status = arg;
     217                 :            : 
     218   [ +  +  +  +  :      12075 :         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   [ +  -  +  -  :      12075 :         memcpy(&status->cpl, cpl, sizeof(*cpl));
                   +  - ]
     231   [ +  -  +  - ]:      12075 :         status->done = true;
     232         [ -  + ]:       2121 : }
     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                 :    2184677 : 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                 :         10 :         int rc;
     245                 :            : 
     246         [ +  + ]:    2184677 :         if (robust_mutex) {
     247                 :     589659 :                 nvme_robust_mutex_lock(robust_mutex);
     248                 :          5 :         }
     249                 :            : 
     250   [ +  +  +  -  :    2184677 :         if (qpair->poll_group) {
                   +  + ]
     251   [ #  #  #  #  :      76094 :                 rc = (int)spdk_nvme_poll_group_process_completions(qpair->poll_group->group, 0,
             #  #  #  # ]
     252                 :            :                                 dummy_disconnected_qpair_cb);
     253                 :          0 :         } else {
     254                 :    2108583 :                 rc = spdk_nvme_qpair_process_completions(qpair, 0);
     255                 :            :         }
     256                 :            : 
     257         [ +  + ]:    2184677 :         if (robust_mutex) {
     258                 :     589659 :                 nvme_robust_mutex_unlock(robust_mutex);
     259                 :          5 :         }
     260                 :            : 
     261         [ +  + ]:    2184677 :         if (rc < 0) {
     262   [ +  -  +  -  :         24 :                 status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
             +  -  +  - ]
     263   [ +  -  +  -  :         24 :                 status->cpl.status.sc = SPDK_NVME_SC_ABORTED_SQ_DELETION;
             +  -  +  - ]
     264                 :         24 :                 goto error;
     265                 :            :         }
     266                 :            : 
     267   [ +  +  +  +  :    2184653 :         if (!status->done && status->timeout_tsc && spdk_get_ticks() > status->timeout_tsc) {
          +  +  +  +  +  
          -  +  -  +  +  
          +  -  +  -  -  
                      + ]
     268                 :         12 :                 goto error;
     269                 :            :         }
     270                 :            : 
     271   [ +  +  +  -  :    2184641 :         if (qpair->ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
          +  -  +  -  +  
                -  +  + ]
     272   [ +  -  +  - ]:      26073 :                 union spdk_nvme_csts_register csts = spdk_nvme_ctrlr_get_regs_csts(qpair->ctrlr);
     273         [ +  + ]:      26073 :                 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      [ -  -  + ]:         36 :         }
     279                 :            : 
     280   [ +  +  +  +  :    2184641 :         if (!status->done) {
             +  -  +  + ]
     281                 :    2172548 :                 return -EAGAIN;
     282   [ +  +  +  +  :      12093 :         } else if (spdk_nvme_cpl_is_error(&status->cpl)) {
          +  -  +  -  +  
          -  -  +  -  +  
          -  +  -  +  -  
                      + ]
     283                 :        790 :                 return -EIO;
     284                 :            :         } else {
     285                 :      11303 :                 return 0;
     286                 :            :         }
     287                 :         30 : 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   [ +  +  +  -  :         36 :         if (!status->done) {
             +  -  -  + ]
     293   [ +  -  +  - ]:         36 :                 status->timed_out = true;
     294                 :          6 :         }
     295                 :            : 
     296                 :         36 :         return -ECANCELED;
     297                 :      48883 : }
     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                 :       5768 : 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                 :         10 :         int rc;
     323                 :            : 
     324         [ +  + ]:       5768 :         if (timeout_in_usecs) {
     325   [ +  -  +  - ]:        262 :                 status->timeout_tsc = spdk_get_ticks() + timeout_in_usecs *
     326   [ +  -  +  - ]:        140 :                                       spdk_get_ticks_hz() / SPDK_SEC_TO_USEC;
     327                 :          6 :         } else {
     328   [ +  -  +  - ]:       5634 :                 status->timeout_tsc = 0;
     329                 :            :         }
     330                 :            : 
     331   [ +  -  +  -  :       5768 :         status->cpl.status_raw = 0;
             +  -  +  - ]
     332                 :         28 :         do {
     333                 :    1860120 :                 rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, robust_mutex);
     334         [ +  + ]:    1860120 :         } while (rc == -EAGAIN);
     335                 :            : 
     336                 :       5778 :         return rc;
     337                 :         10 : }
     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                 :       2106 : 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                 :       2106 :         return nvme_wait_for_completion_robust_lock_timeout(qpair, status, robust_mutex, 0);
     361                 :            : }
     362                 :            : 
     363                 :            : int
     364                 :       3528 : nvme_wait_for_completion(struct spdk_nvme_qpair *qpair,
     365                 :            :                          struct nvme_completion_poll_status *status)
     366                 :            : {
     367                 :       3528 :         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                 :        107 : 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                 :        107 :         return nvme_wait_for_completion_robust_lock_timeout(qpair, status, NULL, timeout_in_usecs);
     391                 :            : }
     392                 :            : 
     393                 :            : static void
     394                 :     260694 : nvme_user_copy_cmd_complete(void *arg, const struct spdk_nvme_cpl *cpl)
     395                 :            : {
     396                 :     260694 :         struct nvme_request *req = arg;
     397                 :          3 :         spdk_nvme_cmd_cb user_cb_fn;
     398                 :          3 :         void *user_cb_arg;
     399                 :          3 :         enum spdk_nvme_data_transfer xfer;
     400                 :            : 
     401   [ +  +  +  -  :     260694 :         if (req->user_buffer && req->payload_size) {
          +  +  +  -  +  
                -  -  + ]
     402                 :            :                 /* Copy back to the user buffer */
     403   [ +  +  +  -  :     253310 :                 assert(nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_CONTIG);
                   #  # ]
     404   [ +  -  +  - ]:     253310 :                 xfer = spdk_nvme_opc_get_data_transfer(req->cmd.opc);
     405   [ +  +  -  + ]:     253310 :                 if (xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST ||
     406                 :          1 :                     xfer == SPDK_NVME_DATA_BIDIRECTIONAL) {
     407   [ +  +  +  -  :      13261 :                         assert(req->pid == getpid());
             +  -  #  # ]
     408   [ +  +  +  +  :      13261 :                         memcpy(req->user_buffer, req->payload.contig_or_cb_arg, req->payload_size);
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     409                 :       4241 :                 }
     410                 :       4242 :         }
     411                 :            : 
     412   [ +  -  +  - ]:     260694 :         user_cb_fn = req->user_cb_fn;
     413   [ +  -  +  - ]:     260694 :         user_cb_arg = req->user_cb_arg;
     414                 :     260694 :         nvme_cleanup_user_req(req);
     415                 :            : 
     416                 :            :         /* Call the user's original callback now that the buffer has been copied */
     417   [ -  +  +  - ]:     260694 :         user_cb_fn(user_cb_arg, cpl);
     418                 :            : 
     419                 :     260694 : }
     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                 :     263599 : 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                 :         14 :         struct nvme_request *req;
     433                 :     263599 :         void *dma_buffer = NULL;
     434                 :            : 
     435   [ +  +  +  + ]:     263599 :         if (buffer && payload_size) {
     436                 :     256215 :                 dma_buffer = spdk_zmalloc(payload_size, 4096, NULL,
     437                 :            :                                           SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA);
     438         [ +  + ]:     256215 :                 if (!dma_buffer) {
     439                 :          6 :                         return NULL;
     440                 :            :                 }
     441                 :            : 
     442   [ +  +  +  + ]:     256209 :                 if (host_to_controller) {
     443   [ -  +  -  + ]:     242929 :                         memcpy(dma_buffer, buffer, payload_size);
     444                 :          8 :                 }
     445                 :       4252 :         }
     446                 :            : 
     447                 :     263593 :         req = nvme_allocate_request_contig(qpair, dma_buffer, payload_size, nvme_user_copy_cmd_complete,
     448                 :            :                                            NULL);
     449         [ +  + ]:     263593 :         if (!req) {
     450                 :       2845 :                 spdk_free(dma_buffer);
     451                 :       2845 :                 return NULL;
     452                 :            :         }
     453                 :            : 
     454   [ +  -  +  - ]:     260748 :         req->user_cb_fn = cb_fn;
     455   [ +  -  +  - ]:     260748 :         req->user_cb_arg = cb_arg;
     456   [ +  -  +  - ]:     260748 :         req->user_buffer = buffer;
     457   [ +  -  +  - ]:     260748 :         req->cb_arg = req;
     458                 :            : 
     459                 :     260748 :         return req;
     460                 :       7432 : }
     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                 :      89297 : 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   [ +  -  +  - ]:      89297 :         struct spdk_nvme_qpair *qpair = req->qpair;
     481   [ +  -  +  - ]:      89297 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     482         [ +  + ]:      89303 :         uint64_t timeout_ticks = nvme_qpair_is_admin_queue(qpair) ?
     483   [ +  +  +  -  :      89297 :                                  active_proc->timeout_admin_ticks : active_proc->timeout_io_ticks;
             +  -  +  - ]
     484                 :            : 
     485   [ +  +  +  -  :      89297 :         assert(active_proc->timeout_cb_fn != NULL);
             +  -  #  # ]
     486                 :            : 
     487   [ +  +  +  +  :      89297 :         if (req->timed_out || req->submit_tick == 0) {
          +  -  +  -  +  
                      + ]
     488                 :       3048 :                 return 0;
     489                 :            :         }
     490                 :            : 
     491   [ +  +  +  -  :      86249 :         if (req->pid != g_spdk_nvme_pid) {
                   +  + ]
     492                 :          6 :                 return 0;
     493                 :            :         }
     494                 :            : 
     495   [ +  +  -  + ]:      86244 :         if (nvme_qpair_is_admin_queue(qpair) &&
     496   [ +  +  +  - ]:        737 :             req->cmd.opc == SPDK_NVME_OPC_ASYNC_EVENT_REQUEST) {
     497                 :          6 :                 return 0;
     498                 :            :         }
     499                 :            : 
     500   [ +  +  +  -  :      86237 :         if (req->submit_tick + timeout_ticks > now_tick) {
                   +  + ]
     501                 :      86231 :                 return 1;
     502                 :            :         }
     503                 :            : 
     504         [ +  - ]:          6 :         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   [ +  -  +  -  :         11 :         active_proc->timeout_cb_fn(active_proc->timeout_cb_arg, ctrlr,
          -  +  +  -  +  
                -  +  - ]
     512         [ -  + ]:          6 :                                    nvme_qpair_is_admin_queue(qpair) ? NULL : qpair,
     513                 :          1 :                                    cid);
     514                 :          6 :         return 0;
     515                 :          6 : }
     516                 :            : 
     517                 :            : int
     518                 :        888 : nvme_robust_mutex_init_shared(pthread_mutex_t *mtx)
     519                 :            : {
     520                 :        888 :         int rc = 0;
     521                 :            : 
     522                 :            : #ifdef __FreeBSD__
     523                 :            :         pthread_mutex_init(mtx, NULL);
     524                 :            : #else
     525                 :        290 :         pthread_mutexattr_t attr;
     526                 :            : 
     527   [ +  +  +  + ]:        888 :         if (pthread_mutexattr_init(&attr)) {
     528                 :         12 :                 return -1;
     529                 :            :         }
     530   [ +  +  +  -  :       1752 :         if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) ||
                   +  + ]
     531   [ +  +  +  + ]:       1713 :             pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST) ||
     532         [ +  + ]:        876 :             pthread_mutex_init(mtx, &attr)) {
     533                 :          6 :                 rc = -1;
     534                 :          1 :         }
     535         [ +  + ]:        876 :         pthread_mutexattr_destroy(&attr);
     536                 :            : #endif
     537                 :            : 
     538                 :        876 :         return rc;
     539                 :         41 : }
     540                 :            : 
     541                 :            : int
     542                 :      70993 : nvme_driver_init(void)
     543                 :            : {
     544                 :            :         static pthread_mutex_t g_init_mutex = PTHREAD_MUTEX_INITIALIZER;
     545                 :      70993 :         int ret = 0;
     546                 :            :         /* Any socket ID */
     547                 :      70993 :         int socket_id = -1;
     548                 :            : 
     549                 :            :         /* Use a special process-private mutex to ensure the global
     550                 :            :          * nvme driver object (g_spdk_nvme_driver) gets initialized by
     551                 :            :          * only one thread.  Once that object is established and its
     552                 :            :          * mutex is initialized, we can unlock this mutex and use that
     553                 :            :          * one instead.
     554                 :            :          */
     555         [ +  + ]:      70993 :         pthread_mutex_lock(&g_init_mutex);
     556                 :            : 
     557                 :            :         /* Each process needs its own pid. */
     558                 :      70993 :         g_spdk_nvme_pid = getpid();
     559                 :            : 
     560                 :            :         /*
     561                 :            :          * Only one thread from one process will do this driver init work.
     562                 :            :          * The primary process will reserve the shared memory and do the
     563                 :            :          *  initialization.
     564                 :            :          * The secondary process will lookup the existing reserved memory.
     565                 :            :          */
     566         [ +  + ]:      70993 :         if (spdk_process_is_primary()) {
     567                 :            :                 /* The unique named memzone already reserved. */
     568         [ +  + ]:      70751 :                 if (g_spdk_nvme_driver != NULL) {
     569         [ +  + ]:      69875 :                         pthread_mutex_unlock(&g_init_mutex);
     570                 :      69875 :                         return 0;
     571                 :            :                 } else {
     572                 :        876 :                         g_spdk_nvme_driver = spdk_memzone_reserve(SPDK_NVME_DRIVER_NAME,
     573                 :         39 :                                              sizeof(struct nvme_driver), socket_id,
     574                 :            :                                              SPDK_MEMZONE_NO_IOVA_CONTIG);
     575                 :            :                 }
     576                 :            : 
     577         [ +  + ]:        876 :                 if (g_spdk_nvme_driver == NULL) {
     578                 :          6 :                         SPDK_ERRLOG("primary process failed to reserve memory\n");
     579         [ +  + ]:          6 :                         pthread_mutex_unlock(&g_init_mutex);
     580                 :          6 :                         return -1;
     581                 :            :                 }
     582                 :         38 :         } else {
     583                 :        242 :                 g_spdk_nvme_driver = spdk_memzone_lookup(SPDK_NVME_DRIVER_NAME);
     584                 :            : 
     585                 :            :                 /* The unique named memzone already reserved by the primary process. */
     586         [ +  + ]:        242 :                 if (g_spdk_nvme_driver != NULL) {
     587                 :        224 :                         int ms_waited = 0;
     588                 :            : 
     589                 :            :                         /* Wait the nvme driver to get initialized. */
     590   [ +  +  +  +  :        925 :                         while ((g_spdk_nvme_driver->initialized == false) &&
          +  -  +  +  +  
                      + ]
     591         [ +  + ]:        606 :                                (ms_waited < g_nvme_driver_timeout_ms)) {
     592         [ +  - ]:        600 :                                 ms_waited++;
     593                 :        600 :                                 nvme_delay(1000); /* delay 1ms */
     594                 :            :                         }
     595   [ +  +  +  +  :        224 :                         if (g_spdk_nvme_driver->initialized == false) {
             +  -  +  + ]
     596                 :          6 :                                 SPDK_ERRLOG("timeout waiting for primary process to init\n");
     597         [ +  + ]:          6 :                                 pthread_mutex_unlock(&g_init_mutex);
     598                 :          6 :                                 return -1;
     599                 :            :                         }
     600         [ +  + ]:          9 :                 } else {
     601                 :         18 :                         SPDK_ERRLOG("primary process is not started yet\n");
     602         [ +  + ]:         18 :                         pthread_mutex_unlock(&g_init_mutex);
     603                 :         18 :                         return -1;
     604                 :            :                 }
     605                 :            : 
     606         [ +  + ]:        218 :                 pthread_mutex_unlock(&g_init_mutex);
     607                 :        218 :                 return 0;
     608                 :            :         }
     609                 :            : 
     610                 :            :         /*
     611                 :            :          * At this moment, only one thread from the primary process will do
     612                 :            :          * the g_spdk_nvme_driver initialization
     613                 :            :          */
     614   [ +  +  #  # ]:        870 :         assert(spdk_process_is_primary());
     615                 :            : 
     616         [ +  - ]:        870 :         ret = nvme_robust_mutex_init_shared(&g_spdk_nvme_driver->lock);
     617         [ +  + ]:        870 :         if (ret != 0) {
     618                 :          6 :                 SPDK_ERRLOG("failed to initialize mutex\n");
     619                 :          6 :                 spdk_memzone_free(SPDK_NVME_DRIVER_NAME);
     620         [ +  + ]:          6 :                 pthread_mutex_unlock(&g_init_mutex);
     621                 :          6 :                 return ret;
     622                 :            :         }
     623                 :            : 
     624                 :            :         /* The lock in the shared g_spdk_nvme_driver object is now ready to
     625                 :            :          * be used - so we can unlock the g_init_mutex here.
     626                 :            :          */
     627         [ +  + ]:        864 :         pthread_mutex_unlock(&g_init_mutex);
     628         [ +  - ]:        864 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     629                 :            : 
     630   [ +  -  +  - ]:        864 :         g_spdk_nvme_driver->initialized = false;
     631   [ +  -  +  - ]:        864 :         g_spdk_nvme_driver->hotplug_fd = spdk_pci_event_listen();
     632   [ +  +  +  -  :        864 :         if (g_spdk_nvme_driver->hotplug_fd < 0) {
                   +  - ]
     633   [ #  #  #  #  :          0 :                 SPDK_DEBUGLOG(nvme, "Failed to open uevent netlink socket\n");
                   #  # ]
     634                 :          0 :         }
     635                 :            : 
     636   [ +  -  +  -  :        864 :         TAILQ_INIT(&g_spdk_nvme_driver->shared_attached_ctrlrs);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     637                 :            : 
     638         [ +  - ]:        864 :         spdk_uuid_generate(&g_spdk_nvme_driver->default_extended_host_id);
     639                 :            : 
     640         [ +  - ]:        864 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     641                 :            : 
     642                 :        864 :         return ret;
     643                 :       2144 : }
     644                 :            : 
     645                 :            : /* This function must only be called while holding g_spdk_nvme_driver->lock */
     646                 :            : int
     647                 :       2562 : nvme_ctrlr_probe(const struct spdk_nvme_transport_id *trid,
     648                 :            :                  struct spdk_nvme_probe_ctx *probe_ctx, void *devhandle)
     649                 :            : {
     650                 :          5 :         struct spdk_nvme_ctrlr *ctrlr;
     651                 :        373 :         struct spdk_nvme_ctrlr_opts opts;
     652                 :            : 
     653   [ +  +  #  # ]:       2562 :         assert(trid != NULL);
     654                 :            : 
     655                 :       2562 :         spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts, sizeof(opts));
     656                 :            : 
     657   [ +  +  +  +  :       2562 :         if (!probe_ctx->probe_cb || probe_ctx->probe_cb(probe_ctx->cb_ctx, trid, &opts)) {
          +  +  +  -  +  
          -  -  +  +  -  
          +  -  +  -  +  
                      + ]
     658                 :       2534 :                 ctrlr = nvme_get_ctrlr_by_trid_unsafe(trid);
     659         [ -  + ]:       2534 :                 if (ctrlr) {
     660                 :            :                         /* This ctrlr already exists. */
     661                 :            : 
     662   [ #  #  #  #  :          0 :                         if (ctrlr->is_destructed) {
             #  #  #  # ]
     663                 :            :                                 /* This ctrlr is being destructed asynchronously. */
     664         [ #  # ]:          0 :                                 SPDK_ERRLOG("NVMe controller for SSD: %s is being destructed\n",
     665                 :            :                                             trid->traddr);
     666                 :          0 :                                 return -EBUSY;
     667                 :            :                         }
     668                 :            : 
     669                 :            :                         /* Increase the ref count before calling attach_cb() as the user may
     670                 :            :                         * call nvme_detach() immediately. */
     671                 :          0 :                         nvme_ctrlr_proc_get_ref(ctrlr);
     672                 :            : 
     673   [ #  #  #  #  :          0 :                         if (probe_ctx->attach_cb) {
                   #  # ]
     674         [ #  # ]:          0 :                                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     675   [ #  #  #  #  :          0 :                                 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     676         [ #  # ]:          0 :                                 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     677                 :          0 :                         }
     678                 :          0 :                         return 0;
     679                 :            :                 }
     680                 :            : 
     681                 :       2534 :                 ctrlr = nvme_transport_ctrlr_construct(trid, &opts, devhandle);
     682         [ +  + ]:       2534 :                 if (ctrlr == NULL) {
     683         [ +  - ]:         12 :                         SPDK_ERRLOG("Failed to construct NVMe controller for SSD: %s\n", trid->traddr);
     684                 :         12 :                         return -1;
     685                 :            :                 }
     686   [ +  -  +  -  :       2522 :                 ctrlr->remove_cb = probe_ctx->remove_cb;
             +  -  +  - ]
     687   [ +  -  +  -  :       2522 :                 ctrlr->cb_ctx = probe_ctx->cb_ctx;
             +  -  +  - ]
     688                 :            : 
     689   [ +  -  +  - ]:       2522 :                 nvme_qpair_set_state(ctrlr->adminq, NVME_QPAIR_ENABLED);
     690   [ +  -  +  -  :       2522 :                 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     691                 :       2522 :                 return 0;
     692                 :            :         }
     693                 :            : 
     694                 :         28 :         return 1;
     695                 :       1065 : }
     696                 :            : 
     697                 :            : static void
     698                 :  159295560 : nvme_ctrlr_poll_internal(struct spdk_nvme_ctrlr *ctrlr,
     699                 :            :                          struct spdk_nvme_probe_ctx *probe_ctx)
     700                 :            : {
     701                 :  159295560 :         int rc = 0;
     702                 :            : 
     703                 :  159295560 :         rc = nvme_ctrlr_process_init(ctrlr);
     704                 :            : 
     705         [ +  + ]:  159295560 :         if (rc) {
     706                 :            :                 /* Controller failed to initialize. */
     707   [ +  +  +  -  :         18 :                 TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     708   [ +  -  +  - ]:         18 :                 SPDK_ERRLOG("Failed to initialize SSD: %s\n", ctrlr->trid.traddr);
     709                 :         18 :                 nvme_ctrlr_lock(ctrlr);
     710                 :         18 :                 nvme_ctrlr_fail(ctrlr, false);
     711                 :         18 :                 nvme_ctrlr_unlock(ctrlr);
     712                 :         18 :                 nvme_ctrlr_destruct(ctrlr);
     713                 :         18 :                 return;
     714                 :            :         }
     715                 :            : 
     716   [ +  +  +  -  :  159295542 :         if (ctrlr->state != NVME_CTRLR_STATE_READY) {
                   +  + ]
     717                 :  159292995 :                 return;
     718                 :            :         }
     719                 :            : 
     720   [ +  -  +  -  :       2547 :         STAILQ_INIT(&ctrlr->io_producers);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     721                 :            : 
     722                 :            :         /*
     723                 :            :          * Controller has been initialized.
     724                 :            :          *  Move it to the attached_ctrlrs list.
     725                 :            :          */
     726   [ +  +  +  -  :       2547 :         TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     727                 :            : 
     728         [ +  - ]:       2547 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     729         [ +  + ]:       2547 :         if (nvme_ctrlr_shared(ctrlr)) {
     730   [ +  -  +  -  :        656 :                 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     731                 :          3 :         } else {
     732   [ +  -  +  -  :       1891 :                 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     733                 :            :         }
     734                 :            : 
     735                 :            :         /*
     736                 :            :          * Increase the ref count before calling attach_cb() as the user may
     737                 :            :          * call nvme_detach() immediately.
     738                 :            :          */
     739                 :       2547 :         nvme_ctrlr_proc_get_ref(ctrlr);
     740         [ +  - ]:       2547 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     741                 :            : 
     742   [ +  +  +  -  :       2547 :         if (probe_ctx->attach_cb) {
                   +  + ]
     743   [ +  -  +  -  :       1057 :                 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     744                 :          2 :         }
     745         [ -  + ]:   33025687 : }
     746                 :            : 
     747                 :            : static int
     748                 :      63429 : nvme_init_controllers(struct spdk_nvme_probe_ctx *probe_ctx)
     749                 :            : {
     750                 :      63429 :         int rc = 0;
     751                 :            : 
     752                 :   33023654 :         while (true) {
     753                 :  159165281 :                 rc = spdk_nvme_probe_poll_async(probe_ctx);
     754         [ +  + ]:  159165281 :                 if (rc != -EAGAIN) {
     755                 :      63443 :                         return rc;
     756                 :            :                 }
     757                 :            :         }
     758                 :            : 
     759                 :            :         return rc;
     760                 :         14 : }
     761                 :            : 
     762                 :            : /* This function must not be called while holding g_spdk_nvme_driver->lock */
     763                 :            : static struct spdk_nvme_ctrlr *
     764                 :       1576 : nvme_get_ctrlr_by_trid(const struct spdk_nvme_transport_id *trid)
     765                 :            : {
     766                 :         13 :         struct spdk_nvme_ctrlr *ctrlr;
     767                 :            : 
     768         [ +  - ]:       1576 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     769                 :       1576 :         ctrlr = nvme_get_ctrlr_by_trid_unsafe(trid);
     770         [ +  - ]:       1576 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     771                 :            : 
     772                 :       1589 :         return ctrlr;
     773                 :         13 : }
     774                 :            : 
     775                 :            : /* This function must be called while holding g_spdk_nvme_driver->lock */
     776                 :            : struct spdk_nvme_ctrlr *
     777                 :       5043 : nvme_get_ctrlr_by_trid_unsafe(const struct spdk_nvme_transport_id *trid)
     778                 :            : {
     779                 :         17 :         struct spdk_nvme_ctrlr *ctrlr;
     780                 :            : 
     781                 :            :         /* Search per-process list */
     782   [ +  +  #  #  :       5361 :         TAILQ_FOREACH(ctrlr, &g_nvme_attached_ctrlrs, tailq) {
             #  #  #  # ]
     783   [ +  +  -  + ]:       1766 :                 if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) == 0) {
     784                 :       1448 :                         return ctrlr;
     785                 :            :                 }
     786                 :          0 :         }
     787                 :            : 
     788                 :            :         /* Search multi-process shared list */
     789   [ +  +  +  -  :       4116 :         TAILQ_FOREACH(ctrlr, &g_spdk_nvme_driver->shared_attached_ctrlrs, tailq) {
          +  -  +  +  #  
             #  #  #  #  
                      # ]
     790   [ +  +  -  + ]:        904 :                 if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) == 0) {
     791                 :        383 :                         return ctrlr;
     792                 :            :                 }
     793                 :          0 :         }
     794                 :            : 
     795                 :       3212 :         return NULL;
     796                 :       2137 : }
     797                 :            : 
     798                 :            : /* This function must only be called while holding g_spdk_nvme_driver->lock */
     799                 :            : static int
     800                 :      67227 : nvme_probe_internal(struct spdk_nvme_probe_ctx *probe_ctx,
     801                 :            :                     bool direct_connect)
     802                 :            : {
     803                 :         13 :         int rc;
     804                 :         13 :         struct spdk_nvme_ctrlr *ctrlr, *ctrlr_tmp;
     805                 :            : 
     806   [ +  +  +  -  :      67227 :         if (strlen(probe_ctx->trid.trstring) == 0) {
             +  -  +  + ]
     807                 :            :                 /* If user didn't provide trstring, derive it from trtype */
     808   [ +  -  +  -  :        111 :                 spdk_nvme_trid_populate_transport(&probe_ctx->trid, probe_ctx->trid.trtype);
             +  -  +  - ]
     809                 :         17 :         }
     810                 :            : 
     811   [ +  +  +  -  :      67227 :         if (!spdk_nvme_transport_available_by_name(probe_ctx->trid.trstring)) {
                   +  + ]
     812   [ +  -  +  -  :          6 :                 SPDK_ERRLOG("NVMe trtype %u (%s) not available\n",
          +  -  +  -  +  
                      - ]
     813                 :            :                             probe_ctx->trid.trtype, probe_ctx->trid.trstring);
     814                 :          6 :                 return -1;
     815                 :            :         }
     816                 :            : 
     817         [ +  - ]:      67221 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     818                 :            : 
     819         [ +  - ]:      67221 :         rc = nvme_transport_ctrlr_scan(probe_ctx, direct_connect);
     820         [ +  + ]:      67221 :         if (rc != 0) {
     821                 :         18 :                 SPDK_ERRLOG("NVMe ctrlr scan failed\n");
     822   [ +  +  +  -  :         24 :                 TAILQ_FOREACH_SAFE(ctrlr, &probe_ctx->init_ctrlrs, tailq, ctrlr_tmp) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
     823   [ +  +  +  -  :          6 :                         TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     824                 :          6 :                         nvme_transport_ctrlr_destruct(ctrlr);
     825                 :          1 :                 }
     826         [ +  - ]:         18 :                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     827                 :         18 :                 return -1;
     828                 :            :         }
     829                 :            : 
     830                 :            :         /*
     831                 :            :          * Probe controllers on the shared_attached_ctrlrs list
     832                 :            :          */
     833   [ +  +  +  -  :      67203 :         if (!spdk_process_is_primary() && (probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE)) {
          +  -  +  -  -  
                      + ]
     834   [ +  +  -  +  :        492 :                 TAILQ_FOREACH(ctrlr, &g_spdk_nvme_driver->shared_attached_ctrlrs, tailq) {
          -  +  +  +  +  
             -  +  -  +  
                      - ]
     835                 :            :                         /* Do not attach other ctrlrs if user specify a valid trid */
     836   [ +  +  +  +  :        384 :                         if ((strlen(probe_ctx->trid.traddr) != 0) &&
          +  -  +  +  +  
                      - ]
     837   [ +  -  +  - ]:         84 :                             (spdk_nvme_transport_id_compare(&probe_ctx->trid, &ctrlr->trid))) {
     838                 :         30 :                                 continue;
     839                 :            :                         }
     840                 :            : 
     841                 :            :                         /* Do not attach if we failed to initialize it in this process */
     842         [ +  + ]:        270 :                         if (nvme_ctrlr_get_current_process(ctrlr) == NULL) {
     843                 :          0 :                                 continue;
     844                 :            :                         }
     845                 :            : 
     846                 :        270 :                         nvme_ctrlr_proc_get_ref(ctrlr);
     847                 :            : 
     848                 :            :                         /*
     849                 :            :                          * Unlock while calling attach_cb() so the user can call other functions
     850                 :            :                          *  that may take the driver lock, like nvme_detach().
     851                 :            :                          */
     852   [ +  +  +  -  :        270 :                         if (probe_ctx->attach_cb) {
                   +  + ]
     853         [ +  - ]:        220 :                                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     854   [ +  -  +  -  :        220 :                                 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     855         [ +  - ]:        220 :                                 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     856                 :          1 :                         }
     857                 :          6 :                 }
     858                 :          7 :         }
     859                 :            : 
     860         [ +  - ]:      67203 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     861                 :            : 
     862                 :      67203 :         return 0;
     863                 :       1073 : }
     864                 :            : 
     865                 :            : static void
     866                 :      67245 : nvme_probe_ctx_init(struct spdk_nvme_probe_ctx *probe_ctx,
     867                 :            :                     const struct spdk_nvme_transport_id *trid,
     868                 :            :                     void *cb_ctx,
     869                 :            :                     spdk_nvme_probe_cb probe_cb,
     870                 :            :                     spdk_nvme_attach_cb attach_cb,
     871                 :            :                     spdk_nvme_remove_cb remove_cb)
     872                 :            : {
     873         [ +  - ]:      67245 :         probe_ctx->trid = *trid;
     874   [ +  -  +  - ]:      67245 :         probe_ctx->cb_ctx = cb_ctx;
     875   [ +  -  +  - ]:      67245 :         probe_ctx->probe_cb = probe_cb;
     876   [ +  -  +  - ]:      67245 :         probe_ctx->attach_cb = attach_cb;
     877   [ +  -  +  - ]:      67245 :         probe_ctx->remove_cb = remove_cb;
     878   [ +  -  +  -  :      67245 :         TAILQ_INIT(&probe_ctx->init_ctrlrs);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     879                 :      67245 : }
     880                 :            : 
     881                 :            : int
     882                 :      61873 : spdk_nvme_probe(const struct spdk_nvme_transport_id *trid, void *cb_ctx,
     883                 :            :                 spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb attach_cb,
     884                 :            :                 spdk_nvme_remove_cb remove_cb)
     885                 :            : {
     886                 :        108 :         struct spdk_nvme_transport_id trid_pcie;
     887                 :          4 :         struct spdk_nvme_probe_ctx *probe_ctx;
     888                 :            : 
     889         [ +  + ]:      61873 :         if (trid == NULL) {
     890         [ +  + ]:      61624 :                 memset(&trid_pcie, 0, sizeof(trid_pcie));
     891                 :      61624 :                 spdk_nvme_trid_populate_transport(&trid_pcie, SPDK_NVME_TRANSPORT_PCIE);
     892                 :      61624 :                 trid = &trid_pcie;
     893                 :          5 :         }
     894                 :            : 
     895                 :      61878 :         probe_ctx = spdk_nvme_probe_async(trid, cb_ctx, probe_cb,
     896                 :          5 :                                           attach_cb, remove_cb);
     897         [ +  + ]:      61873 :         if (!probe_ctx) {
     898                 :         14 :                 SPDK_ERRLOG("Create probe context failed\n");
     899                 :         14 :                 return -1;
     900                 :            :         }
     901                 :            : 
     902                 :            :         /*
     903                 :            :          * Keep going even if one or more nvme_attach() calls failed,
     904                 :            :          *  but maintain the value of rc to signal errors when we return.
     905                 :            :          */
     906                 :      61859 :         return nvme_init_controllers(probe_ctx);
     907                 :          5 : }
     908                 :            : 
     909                 :            : static bool
     910                 :        896 : nvme_connect_probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     911                 :            :                       struct spdk_nvme_ctrlr_opts *opts)
     912                 :            : {
     913                 :        896 :         struct spdk_nvme_ctrlr_opts *requested_opts = cb_ctx;
     914                 :            : 
     915   [ +  +  #  # ]:        896 :         assert(requested_opts);
     916   [ +  +  +  + ]:        896 :         memcpy(opts, requested_opts, sizeof(*opts));
     917                 :            : 
     918                 :        896 :         return true;
     919                 :          4 : }
     920                 :            : 
     921                 :            : static void
     922                 :         81 : nvme_ctrlr_opts_init(struct spdk_nvme_ctrlr_opts *opts,
     923                 :            :                      const struct spdk_nvme_ctrlr_opts *opts_user,
     924                 :            :                      size_t opts_size_user)
     925                 :            : {
     926   [ +  +  #  # ]:         81 :         assert(opts);
     927   [ +  +  #  # ]:         81 :         assert(opts_user);
     928                 :            : 
     929                 :         81 :         spdk_nvme_ctrlr_get_default_ctrlr_opts(opts, opts_size_user);
     930                 :            : 
     931                 :            : #define FIELD_OK(field) \
     932                 :            :         offsetof(struct spdk_nvme_ctrlr_opts, field) + sizeof(opts->field) <= (opts->opts_size)
     933                 :            : 
     934                 :            : #define SET_FIELD(field) \
     935                 :            :         if (FIELD_OK(field)) { \
     936                 :            :                         opts->field = opts_user->field; \
     937                 :            :         }
     938                 :            : 
     939                 :            : #define SET_FIELD_ARRAY(field) \
     940                 :            :         if (FIELD_OK(field)) { \
     941                 :            :                 memcpy(opts->field, opts_user->field, sizeof(opts_user->field)); \
     942                 :            :         }
     943                 :            : 
     944   [ +  +  +  -  :         81 :         SET_FIELD(num_io_queues);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     945   [ +  +  +  +  :         81 :         SET_FIELD(use_cmb_sqs);
          +  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     946   [ +  +  +  +  :         81 :         SET_FIELD(no_shn_notification);
          +  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     947   [ +  +  +  -  :         81 :         SET_FIELD(arb_mechanism);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     948   [ +  +  +  -  :         81 :         SET_FIELD(arbitration_burst);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     949   [ +  +  +  -  :         81 :         SET_FIELD(low_priority_weight);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     950   [ +  +  +  -  :         81 :         SET_FIELD(medium_priority_weight);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     951   [ +  +  +  -  :         81 :         SET_FIELD(high_priority_weight);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     952   [ +  +  +  -  :         81 :         SET_FIELD(keep_alive_timeout_ms);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     953   [ +  +  +  -  :         81 :         SET_FIELD(transport_retry_count);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     954   [ +  +  +  -  :         81 :         SET_FIELD(io_queue_size);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     955   [ +  +  +  +  :         81 :         SET_FIELD_ARRAY(hostnqn);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     956   [ +  +  +  -  :         81 :         SET_FIELD(io_queue_requests);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     957   [ +  +  +  +  :         81 :         SET_FIELD_ARRAY(src_addr);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     958   [ +  +  +  +  :         81 :         SET_FIELD_ARRAY(src_svcid);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     959   [ +  +  +  -  :         81 :         SET_FIELD_ARRAY(host_id);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     960   [ +  +  +  -  :         81 :         SET_FIELD_ARRAY(extended_host_id);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     961   [ +  +  +  -  :         81 :         SET_FIELD(command_set);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     962   [ +  +  +  -  :         81 :         SET_FIELD(admin_timeout_ms);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     963   [ +  +  +  +  :         81 :         SET_FIELD(header_digest);
          +  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     964   [ +  +  +  +  :         81 :         SET_FIELD(data_digest);
          +  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     965   [ +  +  +  +  :         81 :         SET_FIELD(disable_error_logging);
          +  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     966   [ +  +  +  -  :         81 :         SET_FIELD(transport_ack_timeout);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     967   [ +  +  +  -  :         81 :         SET_FIELD(admin_queue_size);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     968   [ +  +  +  -  :         81 :         SET_FIELD(fabrics_connect_timeout_us);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     969   [ +  +  +  +  :         81 :         SET_FIELD(disable_read_ana_log_page);
          +  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     970   [ +  +  +  -  :         81 :         SET_FIELD(disable_read_changed_ns_list_log_page);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     971   [ +  +  +  +  :         81 :         SET_FIELD_ARRAY(psk);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     972                 :            : 
     973                 :            : #undef FIELD_OK
     974                 :            : #undef SET_FIELD
     975                 :            : #undef SET_FIELD_ARRAY
     976                 :         81 : }
     977                 :            : 
     978                 :            : struct spdk_nvme_ctrlr *
     979                 :       1564 : spdk_nvme_connect(const struct spdk_nvme_transport_id *trid,
     980                 :            :                   const struct spdk_nvme_ctrlr_opts *opts, size_t opts_size)
     981                 :            : {
     982                 :         11 :         int rc;
     983                 :       1564 :         struct spdk_nvme_ctrlr *ctrlr = NULL;
     984                 :         11 :         struct spdk_nvme_probe_ctx *probe_ctx;
     985                 :       1564 :         struct spdk_nvme_ctrlr_opts *opts_local_p = NULL;
     986                 :         83 :         struct spdk_nvme_ctrlr_opts opts_local;
     987                 :            : 
     988         [ +  + ]:       1564 :         if (trid == NULL) {
     989                 :          6 :                 SPDK_ERRLOG("No transport ID specified\n");
     990                 :          6 :                 return NULL;
     991                 :            :         }
     992                 :            : 
     993         [ +  + ]:       1558 :         if (opts) {
     994                 :         81 :                 opts_local_p = &opts_local;
     995                 :         81 :                 nvme_ctrlr_opts_init(opts_local_p, opts, opts_size);
     996                 :          4 :         }
     997                 :            : 
     998                 :       1558 :         probe_ctx = spdk_nvme_connect_async(trid, opts_local_p, NULL);
     999         [ +  + ]:       1558 :         if (!probe_ctx) {
    1000                 :          6 :                 SPDK_ERRLOG("Create probe context failed\n");
    1001                 :          6 :                 return NULL;
    1002                 :            :         }
    1003                 :            : 
    1004                 :       1552 :         rc = nvme_init_controllers(probe_ctx);
    1005         [ +  + ]:       1552 :         if (rc != 0) {
    1006                 :          0 :                 return NULL;
    1007                 :            :         }
    1008                 :            : 
    1009                 :       1552 :         ctrlr = nvme_get_ctrlr_by_trid(trid);
    1010                 :            : 
    1011                 :       1552 :         return ctrlr;
    1012                 :       1069 : }
    1013                 :            : 
    1014                 :            : void
    1015                 :      81626 : spdk_nvme_trid_populate_transport(struct spdk_nvme_transport_id *trid,
    1016                 :            :                                   enum spdk_nvme_transport_type trtype)
    1017                 :            : {
    1018                 :         14 :         const char *trstring;
    1019                 :            : 
    1020   [ +  -  +  - ]:      81626 :         trid->trtype = trtype;
    1021   [ -  +  +  +  :      81626 :         switch (trtype) {
                +  -  - ]
    1022                 :          0 :         case SPDK_NVME_TRANSPORT_FC:
    1023                 :          0 :                 trstring = SPDK_NVME_TRANSPORT_NAME_FC;
    1024                 :          0 :                 break;
    1025                 :      65695 :         case SPDK_NVME_TRANSPORT_PCIE:
    1026                 :      65712 :                 trstring = SPDK_NVME_TRANSPORT_NAME_PCIE;
    1027                 :      65712 :                 break;
    1028                 :       2395 :         case SPDK_NVME_TRANSPORT_RDMA:
    1029                 :       2395 :                 trstring = SPDK_NVME_TRANSPORT_NAME_RDMA;
    1030                 :       2395 :                 break;
    1031                 :      10334 :         case SPDK_NVME_TRANSPORT_TCP:
    1032                 :      13512 :                 trstring = SPDK_NVME_TRANSPORT_NAME_TCP;
    1033                 :      13512 :                 break;
    1034                 :          0 :         case SPDK_NVME_TRANSPORT_VFIOUSER:
    1035                 :          7 :                 trstring = SPDK_NVME_TRANSPORT_NAME_VFIOUSER;
    1036                 :          7 :                 break;
    1037                 :          0 :         case SPDK_NVME_TRANSPORT_CUSTOM:
    1038                 :          0 :                 trstring = SPDK_NVME_TRANSPORT_NAME_CUSTOM;
    1039                 :          0 :                 break;
    1040                 :          0 :         default:
    1041                 :          0 :                 SPDK_ERRLOG("no available transports\n");
    1042         [ #  # ]:          0 :                 assert(0);
    1043                 :            :                 return;
    1044                 :            :         }
    1045         [ +  + ]:      81626 :         snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", trstring);
    1046                 :       3202 : }
    1047                 :            : 
    1048                 :            : int
    1049                 :       2001 : spdk_nvme_transport_id_populate_trstring(struct spdk_nvme_transport_id *trid, const char *trstring)
    1050                 :            : {
    1051                 :       2001 :         int i = 0;
    1052                 :            : 
    1053                 :            :         /* Note: gcc-11 has some false positive -Wstringop-overread warnings with LTO builds if we
    1054                 :            :          * use strnlen here.  So do the trstring copy manually instead.  See GitHub issue #2391.
    1055                 :            :          */
    1056                 :            : 
    1057                 :            :         /* cast official trstring to uppercase version of input. */
    1058   [ +  +  +  +  :       9295 :         while (i < SPDK_NVMF_TRSTRING_MAX_LEN && trstring[i] != 0) {
             +  -  +  + ]
    1059   [ +  -  +  -  :       7294 :                 trid->trstring[i] = toupper(trstring[i]);
          +  -  +  -  +  
                -  +  - ]
    1060         [ +  - ]:       7294 :                 i++;
    1061                 :            :         }
    1062                 :            : 
    1063   [ +  +  +  -  :       2001 :         if (trstring[i] != 0) {
                   +  - ]
    1064                 :          0 :                 return -EINVAL;
    1065                 :            :         } else {
    1066   [ +  -  +  -  :       2001 :                 trid->trstring[i] = 0;
             +  -  +  - ]
    1067                 :       2001 :                 return 0;
    1068                 :            :         }
    1069                 :         76 : }
    1070                 :            : 
    1071                 :            : int
    1072                 :       1933 : spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
    1073                 :            : {
    1074   [ +  +  +  + ]:       1933 :         if (trtype == NULL || str == NULL) {
    1075                 :         12 :                 return -EINVAL;
    1076                 :            :         }
    1077                 :            : 
    1078   [ +  +  +  +  :       1921 :         if (strcasecmp(str, "PCIe") == 0) {
                   +  + ]
    1079         [ +  - ]:        680 :                 *trtype = SPDK_NVME_TRANSPORT_PCIE;
    1080   [ +  +  +  +  :       1253 :         } else if (strcasecmp(str, "RDMA") == 0) {
                   +  + ]
    1081         [ +  - ]:        228 :                 *trtype = SPDK_NVME_TRANSPORT_RDMA;
    1082   [ +  +  +  +  :       1016 :         } else if (strcasecmp(str, "FC") == 0) {
                   +  + ]
    1083         [ +  - ]:         12 :                 *trtype = SPDK_NVME_TRANSPORT_FC;
    1084   [ +  +  +  +  :       1003 :         } else if (strcasecmp(str, "TCP") == 0) {
                   +  + ]
    1085         [ +  - ]:        923 :                 *trtype = SPDK_NVME_TRANSPORT_TCP;
    1086   [ +  +  +  +  :        131 :         } else if (strcasecmp(str, "VFIOUSER") == 0) {
                   +  + ]
    1087         [ -  + ]:         72 :                 *trtype = SPDK_NVME_TRANSPORT_VFIOUSER;
    1088                 :         14 :         } else {
    1089         [ +  - ]:          6 :                 *trtype = SPDK_NVME_TRANSPORT_CUSTOM;
    1090                 :            :         }
    1091                 :       1921 :         return 0;
    1092                 :         87 : }
    1093                 :            : 
    1094                 :            : const char *
    1095                 :       2345 : spdk_nvme_transport_id_trtype_str(enum spdk_nvme_transport_type trtype)
    1096                 :            : {
    1097   [ +  +  +  +  :       2345 :         switch (trtype) {
                -  -  + ]
    1098                 :        932 :         case SPDK_NVME_TRANSPORT_PCIE:
    1099                 :        933 :                 return "PCIe";
    1100                 :        306 :         case SPDK_NVME_TRANSPORT_RDMA:
    1101                 :        307 :                 return "RDMA";
    1102                 :          5 :         case SPDK_NVME_TRANSPORT_FC:
    1103                 :          6 :                 return "FC";
    1104                 :       1092 :         case SPDK_NVME_TRANSPORT_TCP:
    1105                 :       1093 :                 return "TCP";
    1106                 :          0 :         case SPDK_NVME_TRANSPORT_VFIOUSER:
    1107                 :          0 :                 return "VFIOUSER";
    1108                 :          0 :         case SPDK_NVME_TRANSPORT_CUSTOM:
    1109                 :          0 :                 return "CUSTOM";
    1110                 :          5 :         default:
    1111                 :          6 :                 return NULL;
    1112                 :            :         }
    1113                 :          5 : }
    1114                 :            : 
    1115                 :            : int
    1116                 :        630 : spdk_nvme_transport_id_parse_adrfam(enum spdk_nvmf_adrfam *adrfam, const char *str)
    1117                 :            : {
    1118   [ +  +  +  + ]:        630 :         if (adrfam == NULL || str == NULL) {
    1119                 :         12 :                 return -EINVAL;
    1120                 :            :         }
    1121                 :            : 
    1122   [ +  +  +  +  :        618 :         if (strcasecmp(str, "IPv4") == 0) {
                   +  + ]
    1123         [ +  - ]:        576 :                 *adrfam = SPDK_NVMF_ADRFAM_IPV4;
    1124   [ +  +  +  +  :         96 :         } else if (strcasecmp(str, "IPv6") == 0) {
                   +  + ]
    1125         [ +  - ]:         12 :                 *adrfam = SPDK_NVMF_ADRFAM_IPV6;
    1126   [ +  +  +  +  :         32 :         } else if (strcasecmp(str, "IB") == 0) {
                   +  + ]
    1127         [ +  - ]:         12 :                 *adrfam = SPDK_NVMF_ADRFAM_IB;
    1128   [ +  +  +  +  :         20 :         } else if (strcasecmp(str, "FC") == 0) {
                   +  + ]
    1129         [ -  + ]:         12 :                 *adrfam = SPDK_NVMF_ADRFAM_FC;
    1130                 :          2 :         } else {
    1131                 :          6 :                 return -ENOENT;
    1132                 :            :         }
    1133                 :        612 :         return 0;
    1134                 :         63 : }
    1135                 :            : 
    1136                 :            : const char *
    1137                 :       3144 : spdk_nvme_transport_id_adrfam_str(enum spdk_nvmf_adrfam adrfam)
    1138                 :            : {
    1139   [ +  +  +  +  :       3144 :         switch (adrfam) {
                      + ]
    1140                 :       2214 :         case SPDK_NVMF_ADRFAM_IPV4:
    1141                 :       2215 :                 return "IPv4";
    1142                 :          5 :         case SPDK_NVMF_ADRFAM_IPV6:
    1143                 :          6 :                 return "IPv6";
    1144                 :          5 :         case SPDK_NVMF_ADRFAM_IB:
    1145                 :          6 :                 return "IB";
    1146                 :          5 :         case SPDK_NVMF_ADRFAM_FC:
    1147                 :          6 :                 return "FC";
    1148                 :        910 :         default:
    1149                 :        911 :                 return NULL;
    1150                 :            :         }
    1151                 :          5 : }
    1152                 :            : 
    1153                 :            : static size_t
    1154                 :       1280 : parse_next_key(const char **str, char *key, char *val, size_t key_buf_size, size_t val_buf_size)
    1155                 :            : {
    1156                 :            : 
    1157                 :         38 :         const char *sep, *sep1;
    1158                 :       1280 :         const char *whitespace = " \t\n";
    1159                 :         38 :         size_t key_len, val_len;
    1160                 :            : 
    1161   [ +  +  +  +  :       1280 :         *str += strspn(*str, whitespace);
          +  -  +  -  +  
                      - ]
    1162                 :            : 
    1163   [ +  +  +  - ]:       1280 :         sep = strchr(*str, ':');
    1164         [ +  + ]:       1280 :         if (!sep) {
    1165   [ +  +  +  - ]:         92 :                 sep = strchr(*str, '=');
    1166         [ +  + ]:         92 :                 if (!sep) {
    1167                 :          6 :                         SPDK_ERRLOG("Key without ':' or '=' separator\n");
    1168                 :          6 :                         return 0;
    1169                 :            :                 }
    1170                 :          0 :         } else {
    1171   [ +  +  +  - ]:       1188 :                 sep1 = strchr(*str, '=');
    1172   [ +  +  +  + ]:       1188 :                 if ((sep1 != NULL) && (sep1 < sep)) {
    1173                 :         24 :                         sep = sep1;
    1174                 :          4 :                 }
    1175                 :            :         }
    1176                 :            : 
    1177         [ +  - ]:       1274 :         key_len = sep - *str;
    1178         [ +  + ]:       1274 :         if (key_len >= key_buf_size) {
    1179                 :          6 :                 SPDK_ERRLOG("Key length %zu greater than maximum allowed %zu\n",
    1180                 :            :                             key_len, key_buf_size - 1);
    1181                 :          6 :                 return 0;
    1182                 :            :         }
    1183                 :            : 
    1184   [ +  +  +  +  :       1268 :         memcpy(key, *str, key_len);
                   +  - ]
    1185   [ +  -  +  - ]:       1268 :         key[key_len] = '\0';
    1186                 :            : 
    1187   [ +  -  +  - ]:       1268 :         *str += key_len + 1; /* Skip key: */
    1188   [ +  +  +  +  :       1268 :         val_len = strcspn(*str, whitespace);
                   +  - ]
    1189         [ +  + ]:       1268 :         if (val_len == 0) {
    1190                 :          6 :                 SPDK_ERRLOG("Key without value\n");
    1191                 :          6 :                 return 0;
    1192                 :            :         }
    1193                 :            : 
    1194         [ -  + ]:       1262 :         if (val_len >= val_buf_size) {
    1195                 :          0 :                 SPDK_ERRLOG("Value length %zu greater than maximum allowed %zu\n",
    1196                 :            :                             val_len, val_buf_size - 1);
    1197                 :          0 :                 return 0;
    1198                 :            :         }
    1199                 :            : 
    1200   [ -  +  -  +  :       1262 :         memcpy(val, *str, val_len);
                   -  + ]
    1201   [ -  +  -  + ]:       1262 :         val[val_len] = '\0';
    1202                 :            : 
    1203   [ -  +  -  + ]:       1262 :         *str += val_len;
    1204                 :            : 
    1205                 :       1262 :         return val_len;
    1206                 :        163 : }
    1207                 :            : 
    1208                 :            : int
    1209                 :        424 : spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *str)
    1210                 :            : {
    1211                 :         17 :         size_t val_len;
    1212                 :        149 :         char key[32];
    1213                 :        149 :         char val[1024];
    1214                 :            : 
    1215   [ +  +  +  + ]:        424 :         if (trid == NULL || str == NULL) {
    1216                 :         18 :                 return -EINVAL;
    1217                 :            :         }
    1218                 :            : 
    1219   [ +  +  +  + ]:       1632 :         while (*str != '\0') {
    1220                 :            : 
    1221                 :       1244 :                 val_len = parse_next_key(&str, key, val, sizeof(key), sizeof(val));
    1222                 :            : 
    1223         [ +  + ]:       1244 :                 if (val_len == 0) {
    1224                 :         18 :                         SPDK_ERRLOG("Failed to parse transport ID\n");
    1225                 :         18 :                         return -EINVAL;
    1226                 :            :                 }
    1227                 :            : 
    1228   [ +  +  +  -  :       1226 :                 if (strcasecmp(key, "trtype") == 0) {
                   +  + ]
    1229         [ +  + ]:        388 :                         if (spdk_nvme_transport_id_populate_trstring(trid, val) != 0) {
    1230                 :          0 :                                 SPDK_ERRLOG("invalid transport '%s'\n", val);
    1231                 :          0 :                                 return -EINVAL;
    1232                 :            :                         }
    1233   [ +  +  +  - ]:        388 :                         if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, val) != 0) {
    1234                 :          0 :                                 SPDK_ERRLOG("Unknown trtype '%s'\n", val);
    1235                 :          0 :                                 return -EINVAL;
    1236                 :            :                         }
    1237   [ +  +  +  -  :        874 :                 } else if (strcasecmp(key, "adrfam") == 0) {
                   +  + ]
    1238   [ +  +  +  - ]:        179 :                         if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, val) != 0) {
    1239                 :          0 :                                 SPDK_ERRLOG("Unknown adrfam '%s'\n", val);
    1240                 :          0 :                                 return -EINVAL;
    1241                 :            :                         }
    1242   [ +  +  +  -  :        686 :                 } else if (strcasecmp(key, "traddr") == 0) {
                   +  + ]
    1243         [ +  + ]:        340 :                         if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
    1244                 :          0 :                                 SPDK_ERRLOG("traddr length %zu greater than maximum allowed %u\n",
    1245                 :            :                                             val_len, SPDK_NVMF_TRADDR_MAX_LEN);
    1246                 :          0 :                                 return -EINVAL;
    1247                 :            :                         }
    1248   [ +  +  +  -  :        340 :                         memcpy(trid->traddr, val, val_len + 1);
                   +  - ]
    1249   [ +  +  +  -  :        355 :                 } else if (strcasecmp(key, "trsvcid") == 0) {
                   +  + ]
    1250         [ +  + ]:        179 :                         if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
    1251                 :          0 :                                 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
    1252                 :            :                                             val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
    1253                 :          0 :                                 return -EINVAL;
    1254                 :            :                         }
    1255   [ +  +  +  -  :        179 :                         memcpy(trid->trsvcid, val, val_len + 1);
                   +  - ]
    1256   [ +  +  +  -  :        167 :                 } else if (strcasecmp(key, "priority") == 0) {
                   +  + ]
    1257         [ +  + ]:          6 :                         if (val_len > SPDK_NVMF_PRIORITY_MAX_LEN) {
    1258                 :          0 :                                 SPDK_ERRLOG("priority length %zu greater than maximum allowed %u\n",
    1259                 :            :                                             val_len, SPDK_NVMF_PRIORITY_MAX_LEN);
    1260                 :          0 :                                 return -EINVAL;
    1261                 :            :                         }
    1262   [ +  -  +  - ]:          6 :                         trid->priority = spdk_strtol(val, 10);
    1263   [ +  +  +  -  :        135 :                 } else if (strcasecmp(key, "subnqn") == 0) {
                   -  + ]
    1264         [ +  + ]:        127 :                         if (val_len > SPDK_NVMF_NQN_MAX_LEN) {
    1265                 :          0 :                                 SPDK_ERRLOG("subnqn length %zu greater than maximum allowed %u\n",
    1266                 :            :                                             val_len, SPDK_NVMF_NQN_MAX_LEN);
    1267                 :          0 :                                 return -EINVAL;
    1268                 :            :                         }
    1269   [ +  +  +  -  :        127 :                         memcpy(trid->subnqn, val, val_len + 1);
                   +  - ]
    1270   [ -  +  #  #  :         34 :                 } else if (strcasecmp(key, "hostaddr") == 0) {
                   #  # ]
    1271                 :          0 :                         continue;
    1272   [ -  +  #  #  :          7 :                 } else if (strcasecmp(key, "hostsvcid") == 0) {
                   #  # ]
    1273                 :          0 :                         continue;
    1274   [ +  +  #  #  :          7 :                 } else if (strcasecmp(key, "hostnqn") == 0) {
                   #  # ]
    1275                 :          3 :                         continue;
    1276   [ +  +  #  #  :          4 :                 } else if (strcasecmp(key, "ns") == 0) {
                   #  # ]
    1277                 :            :                         /*
    1278                 :            :                          * Special case.  The namespace id parameter may
    1279                 :            :                          * optionally be passed in the transport id string
    1280                 :            :                          * for an SPDK application (e.g. spdk_nvme_perf)
    1281                 :            :                          * and additionally parsed therein to limit
    1282                 :            :                          * targeting a specific namespace.  For this
    1283                 :            :                          * scenario, just silently ignore this key
    1284                 :            :                          * rather than letting it default to logging
    1285                 :            :                          * it as an invalid key.
    1286                 :            :                          */
    1287                 :          3 :                         continue;
    1288   [ +  -  #  #  :          1 :                 } else if (strcasecmp(key, "alt_traddr") == 0) {
                   #  # ]
    1289                 :            :                         /*
    1290                 :            :                          * Used by applications for enabling transport ID failover.
    1291                 :            :                          * Please see the case above for more information on custom parameters.
    1292                 :            :                          */
    1293                 :          1 :                         continue;
    1294                 :            :                 } else {
    1295                 :          0 :                         SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
    1296                 :            :                 }
    1297                 :            :         }
    1298                 :            : 
    1299                 :        388 :         return 0;
    1300                 :         42 : }
    1301                 :            : 
    1302                 :            : int
    1303                 :         18 : spdk_nvme_host_id_parse(struct spdk_nvme_host_id *hostid, const char *str)
    1304                 :         15 : {
    1305                 :            : 
    1306                 :         18 :         size_t key_size = 32;
    1307                 :         18 :         size_t val_size = 1024;
    1308                 :          3 :         size_t val_len;
    1309         [ +  + ]:         18 :         char key[key_size];
    1310         [ +  + ]:         18 :         char val[val_size];
    1311                 :            : 
    1312   [ +  -  -  + ]:         18 :         if (hostid == NULL || str == NULL) {
    1313                 :          0 :                 return -EINVAL;
    1314                 :            :         }
    1315                 :            : 
    1316   [ +  +  +  + ]:         36 :         while (*str != '\0') {
    1317                 :            : 
    1318                 :         18 :                 val_len = parse_next_key(&str, key, val, key_size, val_size);
    1319                 :            : 
    1320         [ +  + ]:         18 :                 if (val_len == 0) {
    1321                 :          0 :                         SPDK_ERRLOG("Failed to parse host ID\n");
    1322                 :          0 :                         return val_len;
    1323                 :            :                 }
    1324                 :            : 
    1325                 :            :                 /* Ignore the rest of the options from the transport ID. */
    1326   [ +  +  +  +  :         18 :                 if (strcasecmp(key, "trtype") == 0) {
                   +  + ]
    1327                 :          6 :                         continue;
    1328   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "adrfam") == 0) {
                   +  - ]
    1329                 :          0 :                         continue;
    1330   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "traddr") == 0) {
                   +  - ]
    1331                 :          0 :                         continue;
    1332   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "trsvcid") == 0) {
                   +  - ]
    1333                 :          0 :                         continue;
    1334   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "subnqn") == 0) {
                   +  - ]
    1335                 :          0 :                         continue;
    1336   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "priority") == 0) {
                   -  + ]
    1337                 :          0 :                         continue;
    1338   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "ns") == 0) {
                   +  - ]
    1339                 :          0 :                         continue;
    1340   [ +  +  +  +  :         12 :                 } else if (strcasecmp(key, "hostaddr") == 0) {
                   +  + ]
    1341         [ +  + ]:          6 :                         if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
    1342                 :          0 :                                 SPDK_ERRLOG("hostaddr length %zu greater than maximum allowed %u\n",
    1343                 :            :                                             val_len, SPDK_NVMF_TRADDR_MAX_LEN);
    1344                 :          0 :                                 return -EINVAL;
    1345                 :            :                         }
    1346   [ +  +  +  +  :          6 :                         memcpy(hostid->hostaddr, val, val_len + 1);
                   +  - ]
    1347                 :            : 
    1348   [ +  +  +  -  :          7 :                 } else if (strcasecmp(key, "hostsvcid") == 0) {
                   -  + ]
    1349         [ +  + ]:          6 :                         if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
    1350                 :          0 :                                 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
    1351                 :            :                                             val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
    1352                 :          0 :                                 return -EINVAL;
    1353                 :            :                         }
    1354   [ -  +  -  +  :          6 :                         memcpy(hostid->hostsvcid, val, val_len + 1);
                   -  + ]
    1355                 :          1 :                 } else {
    1356                 :          0 :                         SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
    1357                 :            :                 }
    1358                 :            :         }
    1359                 :            : 
    1360                 :         18 :         return 0;
    1361                 :          3 : }
    1362                 :            : 
    1363                 :            : static int
    1364                 :      41869 : cmp_int(int a, int b)
    1365                 :            : {
    1366         [ +  - ]:      41869 :         return a - b;
    1367                 :            : }
    1368                 :            : 
    1369                 :            : int
    1370                 :      21704 : spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
    1371                 :            :                                const struct spdk_nvme_transport_id *trid2)
    1372                 :            : {
    1373                 :         29 :         int cmp;
    1374                 :            : 
    1375   [ +  +  +  -  :      21704 :         if (trid1->trtype == SPDK_NVME_TRANSPORT_CUSTOM) {
                   -  + ]
    1376   [ #  #  #  #  :          0 :                 cmp = strcasecmp(trid1->trstring, trid2->trstring);
             #  #  #  # ]
    1377                 :          0 :         } else {
    1378   [ +  -  +  -  :      21704 :                 cmp = cmp_int(trid1->trtype, trid2->trtype);
             +  -  +  - ]
    1379                 :            :         }
    1380                 :            : 
    1381         [ +  + ]:      21704 :         if (cmp) {
    1382                 :          6 :                 return cmp;
    1383                 :            :         }
    1384                 :            : 
    1385   [ +  +  +  -  :      21698 :         if (trid1->trtype == SPDK_NVME_TRANSPORT_PCIE) {
                   +  + ]
    1386                 :       1224 :                 struct spdk_pci_addr pci_addr1 = {};
    1387                 :       1224 :                 struct spdk_pci_addr pci_addr2 = {};
    1388                 :            : 
    1389                 :            :                 /* Normalize PCI addresses before comparing */
    1390   [ +  -  +  +  :       2448 :                 if (spdk_pci_addr_parse(&pci_addr1, trid1->traddr) < 0 ||
                   +  - ]
    1391         [ +  - ]:       1224 :                     spdk_pci_addr_parse(&pci_addr2, trid2->traddr) < 0) {
    1392                 :          0 :                         return -1;
    1393                 :            :                 }
    1394                 :            : 
    1395                 :            :                 /* PCIe transport ID only uses trtype and traddr */
    1396                 :       1224 :                 return spdk_pci_addr_compare(&pci_addr1, &pci_addr2);
    1397                 :         21 :         }
    1398                 :            : 
    1399   [ +  +  +  +  :      20474 :         cmp = strcasecmp(trid1->traddr, trid2->traddr);
             +  -  +  - ]
    1400         [ +  + ]:      20474 :         if (cmp) {
    1401                 :        309 :                 return cmp;
    1402                 :            :         }
    1403                 :            : 
    1404   [ +  -  +  -  :      20165 :         cmp = cmp_int(trid1->adrfam, trid2->adrfam);
             +  -  +  - ]
    1405         [ +  + ]:      20165 :         if (cmp) {
    1406                 :          6 :                 return cmp;
    1407                 :            :         }
    1408                 :            : 
    1409   [ +  +  +  +  :      20159 :         cmp = strcasecmp(trid1->trsvcid, trid2->trsvcid);
             +  -  +  - ]
    1410         [ +  + ]:      20159 :         if (cmp) {
    1411                 :       1086 :                 return cmp;
    1412                 :            :         }
    1413                 :            : 
    1414   [ +  +  +  +  :      19073 :         cmp = strcmp(trid1->subnqn, trid2->subnqn);
             +  -  +  - ]
    1415         [ +  + ]:      19073 :         if (cmp) {
    1416                 :        498 :                 return cmp;
    1417                 :            :         }
    1418                 :            : 
    1419                 :      18575 :         return 0;
    1420                 :       4485 : }
    1421                 :            : 
    1422                 :            : int
    1423                 :         24 : spdk_nvme_prchk_flags_parse(uint32_t *prchk_flags, const char *str)
    1424                 :            : {
    1425                 :          4 :         size_t val_len;
    1426                 :         20 :         char key[32];
    1427                 :         20 :         char val[1024];
    1428                 :            : 
    1429   [ +  +  -  + ]:         24 :         if (prchk_flags == NULL || str == NULL) {
    1430                 :          6 :                 return -EINVAL;
    1431                 :            :         }
    1432                 :            : 
    1433   [ +  +  +  + ]:         45 :         while (*str != '\0') {
    1434                 :         18 :                 val_len = parse_next_key(&str, key, val, sizeof(key), sizeof(val));
    1435                 :            : 
    1436         [ +  + ]:         18 :                 if (val_len == 0) {
    1437                 :          0 :                         SPDK_ERRLOG("Failed to parse prchk\n");
    1438                 :          0 :                         return -EINVAL;
    1439                 :            :                 }
    1440                 :            : 
    1441   [ +  -  +  -  :         18 :                 if (strcasecmp(key, "prchk") == 0) {
                   +  - ]
    1442   [ +  +  +  -  :         18 :                         if (strcasestr(val, "reftag") != NULL) {
                   +  + ]
    1443   [ -  +  -  + ]:         12 :                                 *prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
    1444                 :          2 :                         }
    1445   [ +  +  +  -  :         18 :                         if (strcasestr(val, "guard") != NULL) {
                   +  + ]
    1446   [ -  +  -  + ]:         12 :                                 *prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
    1447                 :          2 :                         }
    1448                 :          3 :                 } else {
    1449                 :          0 :                         SPDK_ERRLOG("Unknown key '%s'\n", key);
    1450                 :          0 :                         return -EINVAL;
    1451                 :            :                 }
    1452                 :            :         }
    1453                 :            : 
    1454                 :         18 :         return 0;
    1455                 :          4 : }
    1456                 :            : 
    1457                 :            : const char *
    1458                 :         18 : spdk_nvme_prchk_flags_str(uint32_t prchk_flags)
    1459                 :            : {
    1460   [ +  +  +  + ]:         18 :         if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG) {
    1461   [ +  +  +  + ]:         12 :                 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
    1462                 :          6 :                         return "prchk:reftag|guard";
    1463                 :            :                 } else {
    1464                 :          6 :                         return "prchk:reftag";
    1465                 :            :                 }
    1466                 :            :         } else {
    1467   [ +  -  +  - ]:          6 :                 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
    1468                 :          6 :                         return "prchk:guard";
    1469                 :            :                 } else {
    1470                 :          0 :                         return NULL;
    1471                 :            :                 }
    1472                 :            :         }
    1473                 :          3 : }
    1474                 :            : 
    1475                 :            : struct spdk_nvme_probe_ctx *
    1476                 :      64850 : spdk_nvme_probe_async(const struct spdk_nvme_transport_id *trid,
    1477                 :            :                       void *cb_ctx,
    1478                 :            :                       spdk_nvme_probe_cb probe_cb,
    1479                 :            :                       spdk_nvme_attach_cb attach_cb,
    1480                 :            :                       spdk_nvme_remove_cb remove_cb)
    1481                 :            : {
    1482                 :          4 :         int rc;
    1483                 :          4 :         struct spdk_nvme_probe_ctx *probe_ctx;
    1484                 :            : 
    1485                 :      64850 :         rc = nvme_driver_init();
    1486         [ +  + ]:      64850 :         if (rc != 0) {
    1487                 :          6 :                 return NULL;
    1488                 :            :         }
    1489                 :            : 
    1490                 :      64844 :         probe_ctx = calloc(1, sizeof(*probe_ctx));
    1491         [ +  + ]:      64844 :         if (!probe_ctx) {
    1492                 :          0 :                 return NULL;
    1493                 :            :         }
    1494                 :            : 
    1495                 :      64844 :         nvme_probe_ctx_init(probe_ctx, trid, cb_ctx, probe_cb, attach_cb, remove_cb);
    1496                 :      64844 :         rc = nvme_probe_internal(probe_ctx, false);
    1497         [ +  + ]:      64844 :         if (rc != 0) {
    1498                 :          8 :                 free(probe_ctx);
    1499                 :          8 :                 return NULL;
    1500                 :            :         }
    1501                 :            : 
    1502                 :      64836 :         return probe_ctx;
    1503                 :          5 : }
    1504                 :            : 
    1505                 :            : int
    1506                 :  159358941 : spdk_nvme_probe_poll_async(struct spdk_nvme_probe_ctx *probe_ctx)
    1507                 :            : {
    1508                 :         14 :         struct spdk_nvme_ctrlr *ctrlr, *ctrlr_tmp;
    1509                 :            : 
    1510   [ +  +  +  -  :  159358941 :         if (!spdk_process_is_primary() && probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
          +  -  +  -  -  
                      + ]
    1511                 :        192 :                 free(probe_ctx);
    1512                 :        192 :                 return 0;
    1513                 :            :         }
    1514                 :            : 
    1515   [ +  +  +  -  :  318654309 :         TAILQ_FOREACH_SAFE(ctrlr, &probe_ctx->init_ctrlrs, tailq, ctrlr_tmp) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
    1516                 :  159295560 :                 nvme_ctrlr_poll_internal(ctrlr, probe_ctx);
    1517                 :   33025687 :         }
    1518                 :            : 
    1519   [ +  +  +  -  :  159358749 :         if (TAILQ_EMPTY(&probe_ctx->init_ctrlrs)) {
             +  -  +  + ]
    1520         [ -  + ]:      67029 :                 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
    1521   [ -  +  -  + ]:      67029 :                 g_spdk_nvme_driver->initialized = true;
    1522         [ -  + ]:      67029 :                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
    1523                 :      67029 :                 free(probe_ctx);
    1524                 :      67029 :                 return 0;
    1525                 :            :         }
    1526                 :            : 
    1527                 :  159291720 :         return -EAGAIN;
    1528                 :   33025698 : }
    1529                 :            : 
    1530                 :            : struct spdk_nvme_probe_ctx *
    1531                 :       2383 : spdk_nvme_connect_async(const struct spdk_nvme_transport_id *trid,
    1532                 :            :                         const struct spdk_nvme_ctrlr_opts *opts,
    1533                 :            :                         spdk_nvme_attach_cb attach_cb)
    1534                 :            : {
    1535                 :         10 :         int rc;
    1536                 :       2383 :         spdk_nvme_probe_cb probe_cb = NULL;
    1537                 :         10 :         struct spdk_nvme_probe_ctx *probe_ctx;
    1538                 :            : 
    1539                 :       2383 :         rc = nvme_driver_init();
    1540         [ +  + ]:       2383 :         if (rc != 0) {
    1541                 :          6 :                 return NULL;
    1542                 :            :         }
    1543                 :            : 
    1544                 :       2377 :         probe_ctx = calloc(1, sizeof(*probe_ctx));
    1545         [ +  + ]:       2377 :         if (!probe_ctx) {
    1546                 :          0 :                 return NULL;
    1547                 :            :         }
    1548                 :            : 
    1549         [ +  + ]:       2377 :         if (opts) {
    1550                 :        906 :                 probe_cb = nvme_connect_probe_cb;
    1551                 :          5 :         }
    1552                 :            : 
    1553                 :       2377 :         nvme_probe_ctx_init(probe_ctx, trid, (void *)opts, probe_cb, attach_cb, NULL);
    1554                 :       2377 :         rc = nvme_probe_internal(probe_ctx, true);
    1555         [ +  + ]:       2377 :         if (rc != 0) {
    1556                 :         10 :                 free(probe_ctx);
    1557                 :         10 :                 return NULL;
    1558                 :            :         }
    1559                 :            : 
    1560                 :       2367 :         return probe_ctx;
    1561                 :       1069 : }
    1562                 :            : 
    1563                 :            : int
    1564                 :      16781 : nvme_parse_addr(struct sockaddr_storage *sa, int family, const char *addr, const char *service,
    1565                 :            :                 long int *port)
    1566                 :            : {
    1567                 :        113 :         struct addrinfo *res;
    1568                 :        113 :         struct addrinfo hints;
    1569                 :          2 :         int ret;
    1570                 :            : 
    1571         [ +  + ]:      16781 :         memset(&hints, 0, sizeof(hints));
    1572         [ +  - ]:      16781 :         hints.ai_family = family;
    1573         [ +  - ]:      16781 :         hints.ai_socktype = SOCK_STREAM;
    1574         [ +  - ]:      16781 :         hints.ai_protocol = 0;
    1575                 :            : 
    1576   [ +  +  -  + ]:      16781 :         if (addr == NULL || service == NULL) {
    1577                 :          6 :                 SPDK_ERRLOG("addr and service must both be non-NULL\n");
    1578                 :          6 :                 return -EINVAL;
    1579                 :            :         }
    1580                 :            : 
    1581         [ +  - ]:      16775 :         *port = spdk_strtol(service, 10);
    1582   [ +  -  +  +  :      16775 :         if (*port <= 0 || *port >= 65536) {
             +  -  -  + ]
    1583                 :          0 :                 SPDK_ERRLOG("Invalid port: %s\n", service);
    1584                 :          0 :                 return -EINVAL;
    1585                 :            :         }
    1586                 :            : 
    1587                 :      16775 :         ret = getaddrinfo(addr, service, &hints, &res);
    1588         [ -  + ]:      16775 :         if (ret) {
    1589                 :          0 :                 SPDK_ERRLOG("getaddrinfo failed: %s (%d)\n", gai_strerror(ret), ret);
    1590         [ #  # ]:          0 :                 return -(abs(ret));
    1591                 :            :         }
    1592                 :            : 
    1593   [ +  +  +  -  :      16775 :         if (res->ai_addrlen > sizeof(*sa)) {
                   -  + ]
    1594   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("getaddrinfo() ai_addrlen %zu too large\n", (size_t)res->ai_addrlen);
    1595                 :          0 :                 ret = -EINVAL;
    1596                 :          0 :         } else {
    1597   [ +  +  +  +  :      16775 :                 memcpy(sa, res->ai_addr, res->ai_addrlen);
          +  -  +  -  +  
                -  +  - ]
    1598                 :            :         }
    1599                 :            : 
    1600                 :      16775 :         freeaddrinfo(res);
    1601                 :      16775 :         return ret;
    1602                 :       2104 : }
    1603                 :            : 
    1604                 :            : #ifndef SPDK_CONFIG_RDMA
    1605                 :            : void
    1606                 :            : spdk_nvme_rdma_init_hooks(struct spdk_nvme_rdma_hooks *hooks)
    1607                 :            : {
    1608                 :            :         SPDK_ERRLOG("spdk_nvme_rdma_init_hooks() is unsupported: RDMA transport is not available\n");
    1609                 :            :         abort();
    1610                 :            : }
    1611                 :            : #endif
    1612                 :            : 
    1613                 :       2378 : SPDK_LOG_REGISTER_COMPONENT(nvme)

Generated by: LCOV version 1.14