LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_fabric.c (source / functions) Hit Total Coverage
Test: Combined Lines: 267 347 76.9 %
Date: 2024-08-12 15:39:37 Functions: 20 24 83.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 128 210 61.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation. All rights reserved.
       3                 :            :  *   Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
       4                 :            :  *   Copyright (c) 2021, 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : /*
       8                 :            :  * NVMe over Fabrics transport-independent functions
       9                 :            :  */
      10                 :            : 
      11                 :            : #include "nvme_internal.h"
      12                 :            : 
      13                 :            : #include "spdk/endian.h"
      14                 :            : #include "spdk/string.h"
      15                 :            : 
      16                 :            : struct nvme_fabric_prop_ctx {
      17                 :            :         uint64_t                value;
      18                 :            :         int                     size;
      19                 :            :         spdk_nvme_reg_cb        cb_fn;
      20                 :            :         void                    *cb_arg;
      21                 :            : };
      22                 :            : 
      23                 :            : static int
      24                 :       2257 : nvme_fabric_prop_set_cmd(struct spdk_nvme_ctrlr *ctrlr,
      25                 :            :                          uint32_t offset, uint8_t size, uint64_t value,
      26                 :            :                          spdk_nvme_cmd_cb cb_fn, void *cb_arg)
      27                 :            : {
      28                 :       2257 :         struct spdk_nvmf_fabric_prop_set_cmd cmd = {};
      29                 :            : 
      30   [ +  +  -  + ]:       2257 :         assert(size == SPDK_NVMF_PROP_SIZE_4 || size == SPDK_NVMF_PROP_SIZE_8);
      31                 :            : 
      32                 :       2257 :         cmd.opcode = SPDK_NVME_OPC_FABRIC;
      33                 :       2257 :         cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_SET;
      34                 :       2257 :         cmd.ofst = offset;
      35                 :       2257 :         cmd.attrib.size = size;
      36                 :       2257 :         cmd.value.u64 = value;
      37                 :            : 
      38                 :       2257 :         return spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, (struct spdk_nvme_cmd *)&cmd,
      39                 :            :                                              NULL, 0, cb_fn, cb_arg);
      40                 :            : }
      41                 :            : 
      42                 :            : static int
      43                 :          5 : nvme_fabric_prop_set_cmd_sync(struct spdk_nvme_ctrlr *ctrlr,
      44                 :            :                               uint32_t offset, uint8_t size, uint64_t value)
      45                 :            : {
      46                 :            :         struct nvme_completion_poll_status *status;
      47                 :            :         int rc;
      48                 :            : 
      49                 :          5 :         status = calloc(1, sizeof(*status));
      50         [ -  + ]:          5 :         if (!status) {
      51                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
      52                 :          0 :                 return -ENOMEM;
      53                 :            :         }
      54                 :            : 
      55                 :          5 :         rc = nvme_fabric_prop_set_cmd(ctrlr, offset, size, value,
      56                 :            :                                       nvme_completion_poll_cb, status);
      57         [ -  + ]:          5 :         if (rc < 0) {
      58                 :          0 :                 free(status);
      59                 :          0 :                 return rc;
      60                 :            :         }
      61                 :            : 
      62         [ -  + ]:          5 :         if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
      63   [ #  #  #  # ]:          0 :                 if (!status->timed_out) {
      64                 :          0 :                         free(status);
      65                 :            :                 }
      66                 :          0 :                 SPDK_ERRLOG("Property Set failed\n");
      67                 :          0 :                 return -1;
      68                 :            :         }
      69                 :          5 :         free(status);
      70                 :            : 
      71                 :          5 :         return 0;
      72                 :            : }
      73                 :            : 
      74                 :            : static void
      75                 :       2252 : nvme_fabric_prop_set_cmd_done(void *ctx, const struct spdk_nvme_cpl *cpl)
      76                 :            : {
      77                 :       2252 :         struct nvme_fabric_prop_ctx *prop_ctx = ctx;
      78                 :            : 
      79                 :       2252 :         prop_ctx->cb_fn(prop_ctx->cb_arg, prop_ctx->value, cpl);
      80                 :       2252 :         free(prop_ctx);
      81                 :       2252 : }
      82                 :            : 
      83                 :            : static int
      84                 :       2252 : nvme_fabric_prop_set_cmd_async(struct spdk_nvme_ctrlr *ctrlr,
      85                 :            :                                uint32_t offset, uint8_t size, uint64_t value,
      86                 :            :                                spdk_nvme_reg_cb cb_fn, void *cb_arg)
      87                 :            : {
      88                 :            :         struct nvme_fabric_prop_ctx *ctx;
      89                 :            :         int rc;
      90                 :            : 
      91                 :       2252 :         ctx = calloc(1, sizeof(*ctx));
      92         [ -  + ]:       2252 :         if (ctx == NULL) {
      93                 :          0 :                 SPDK_ERRLOG("Failed to allocate fabrics property context\n");
      94                 :          0 :                 return -ENOMEM;
      95                 :            :         }
      96                 :            : 
      97                 :       2252 :         ctx->value = value;
      98                 :       2252 :         ctx->cb_fn = cb_fn;
      99                 :       2252 :         ctx->cb_arg = cb_arg;
     100                 :            : 
     101                 :       2252 :         rc = nvme_fabric_prop_set_cmd(ctrlr, offset, size, value,
     102                 :            :                                       nvme_fabric_prop_set_cmd_done, ctx);
     103         [ -  + ]:       2252 :         if (rc != 0) {
     104                 :          0 :                 SPDK_ERRLOG("Failed to send Property Set fabrics command\n");
     105                 :          0 :                 free(ctx);
     106                 :            :         }
     107                 :            : 
     108                 :       2252 :         return rc;
     109                 :            : }
     110                 :            : 
     111                 :            : static int
     112                 :      45589 : nvme_fabric_prop_get_cmd(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint8_t size,
     113                 :            :                          spdk_nvme_cmd_cb cb_fn, void *cb_arg)
     114                 :            : {
     115                 :      45589 :         struct spdk_nvmf_fabric_prop_set_cmd cmd = {};
     116                 :            : 
     117   [ +  +  -  + ]:      45589 :         assert(size == SPDK_NVMF_PROP_SIZE_4 || size == SPDK_NVMF_PROP_SIZE_8);
     118                 :            : 
     119                 :      45589 :         cmd.opcode = SPDK_NVME_OPC_FABRIC;
     120                 :      45589 :         cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET;
     121                 :      45589 :         cmd.ofst = offset;
     122                 :      45589 :         cmd.attrib.size = size;
     123                 :            : 
     124                 :      45589 :         return spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, (struct spdk_nvme_cmd *)&cmd,
     125                 :            :                                              NULL, 0, cb_fn, cb_arg);
     126                 :            : }
     127                 :            : 
     128                 :            : static int
     129                 :       1200 : nvme_fabric_prop_get_cmd_sync(struct spdk_nvme_ctrlr *ctrlr,
     130                 :            :                               uint32_t offset, uint8_t size, uint64_t *value)
     131                 :            : {
     132                 :            :         struct nvme_completion_poll_status *status;
     133                 :            :         struct spdk_nvmf_fabric_prop_get_rsp *response;
     134                 :            :         int rc;
     135                 :            : 
     136                 :       1200 :         status = calloc(1, sizeof(*status));
     137         [ -  + ]:       1200 :         if (!status) {
     138                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     139                 :          0 :                 return -ENOMEM;
     140                 :            :         }
     141                 :            : 
     142                 :       1200 :         rc = nvme_fabric_prop_get_cmd(ctrlr, offset, size, nvme_completion_poll_cb, status);
     143         [ -  + ]:       1200 :         if (rc < 0) {
     144                 :          0 :                 free(status);
     145                 :          0 :                 return rc;
     146                 :            :         }
     147                 :            : 
     148         [ -  + ]:       1200 :         if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
     149   [ #  #  #  # ]:          0 :                 if (!status->timed_out) {
     150                 :          0 :                         free(status);
     151                 :            :                 }
     152                 :          0 :                 SPDK_ERRLOG("Property Get failed, offset %x, size %u\n", offset, size);
     153                 :          0 :                 return -1;
     154                 :            :         }
     155                 :            : 
     156                 :       1200 :         response = (struct spdk_nvmf_fabric_prop_get_rsp *)&status->cpl;
     157                 :            : 
     158         [ +  + ]:       1200 :         if (size == SPDK_NVMF_PROP_SIZE_4) {
     159                 :       1195 :                 *value = response->value.u32.low;
     160                 :            :         } else {
     161                 :          5 :                 *value = response->value.u64;
     162                 :            :         }
     163                 :            : 
     164                 :       1200 :         free(status);
     165                 :            : 
     166                 :       1200 :         return 0;
     167                 :            : }
     168                 :            : 
     169                 :            : static void
     170                 :      44387 : nvme_fabric_prop_get_cmd_done(void *ctx, const struct spdk_nvme_cpl *cpl)
     171                 :            : {
     172                 :      44387 :         struct nvme_fabric_prop_ctx *prop_ctx = ctx;
     173                 :            :         struct spdk_nvmf_fabric_prop_get_rsp *response;
     174                 :      44387 :         uint64_t value = 0;
     175                 :            : 
     176   [ +  -  +  - ]:      44387 :         if (spdk_nvme_cpl_is_success(cpl)) {
     177                 :      44387 :                 response = (struct spdk_nvmf_fabric_prop_get_rsp *)cpl;
     178                 :            : 
     179      [ +  +  - ]:      44387 :                 switch (prop_ctx->size) {
     180                 :      43239 :                 case SPDK_NVMF_PROP_SIZE_4:
     181                 :      43239 :                         value = response->value.u32.low;
     182                 :      43239 :                         break;
     183                 :       1148 :                 case SPDK_NVMF_PROP_SIZE_8:
     184                 :       1148 :                         value = response->value.u64;
     185                 :       1148 :                         break;
     186                 :          0 :                 default:
     187                 :          0 :                         assert(0 && "Should never happen");
     188                 :            :                 }
     189                 :            :         }
     190                 :            : 
     191                 :      44387 :         prop_ctx->cb_fn(prop_ctx->cb_arg, value, cpl);
     192                 :      44387 :         free(prop_ctx);
     193                 :      44387 : }
     194                 :            : 
     195                 :            : static int
     196                 :      44389 : nvme_fabric_prop_get_cmd_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint8_t size,
     197                 :            :                                spdk_nvme_reg_cb cb_fn, void *cb_arg)
     198                 :            : {
     199                 :            :         struct nvme_fabric_prop_ctx *ctx;
     200                 :            :         int rc;
     201                 :            : 
     202                 :      44389 :         ctx = calloc(1, sizeof(*ctx));
     203         [ -  + ]:      44389 :         if (ctx == NULL) {
     204                 :          0 :                 SPDK_ERRLOG("Failed to allocate fabrics property context\n");
     205                 :          0 :                 return -ENOMEM;
     206                 :            :         }
     207                 :            : 
     208                 :      44389 :         ctx->size = size;
     209                 :      44389 :         ctx->cb_fn = cb_fn;
     210                 :      44389 :         ctx->cb_arg = cb_arg;
     211                 :            : 
     212                 :      44389 :         rc = nvme_fabric_prop_get_cmd(ctrlr, offset, size, nvme_fabric_prop_get_cmd_done, ctx);
     213         [ +  + ]:      44389 :         if (rc != 0) {
     214                 :          2 :                 SPDK_ERRLOG("Failed to send Property Get fabrics command\n");
     215                 :          2 :                 free(ctx);
     216                 :            :         }
     217                 :            : 
     218                 :      44389 :         return rc;
     219                 :            : }
     220                 :            : 
     221                 :            : int
     222                 :          0 : nvme_fabric_ctrlr_set_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t value)
     223                 :            : {
     224                 :          0 :         return nvme_fabric_prop_set_cmd_sync(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, value);
     225                 :            : }
     226                 :            : 
     227                 :            : int
     228                 :          0 : nvme_fabric_ctrlr_set_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value)
     229                 :            : {
     230                 :          0 :         return nvme_fabric_prop_set_cmd_sync(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, value);
     231                 :            : }
     232                 :            : 
     233                 :            : int
     234                 :       1190 : nvme_fabric_ctrlr_get_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t *value)
     235                 :            : {
     236                 :          0 :         uint64_t tmp_value;
     237                 :            :         int rc;
     238                 :       1190 :         rc = nvme_fabric_prop_get_cmd_sync(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, &tmp_value);
     239                 :            : 
     240         [ +  - ]:       1190 :         if (!rc) {
     241                 :       1190 :                 *value = (uint32_t)tmp_value;
     242                 :            :         }
     243                 :       1190 :         return rc;
     244                 :            : }
     245                 :            : 
     246                 :            : int
     247                 :          0 : nvme_fabric_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value)
     248                 :            : {
     249                 :          0 :         return nvme_fabric_prop_get_cmd_sync(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, value);
     250                 :            : }
     251                 :            : 
     252                 :            : int
     253                 :       2252 : nvme_fabric_ctrlr_set_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
     254                 :            :                                   uint32_t value, spdk_nvme_reg_cb cb_fn, void *cb_arg)
     255                 :            : {
     256                 :       2252 :         return nvme_fabric_prop_set_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, value,
     257                 :            :                                               cb_fn, cb_arg);
     258                 :            : }
     259                 :            : 
     260                 :            : int
     261                 :          0 : nvme_fabric_ctrlr_set_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
     262                 :            :                                   uint64_t value, spdk_nvme_reg_cb cb_fn, void *cb_arg)
     263                 :            : {
     264                 :          0 :         return nvme_fabric_prop_set_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, value,
     265                 :            :                                               cb_fn, cb_arg);
     266                 :            : }
     267                 :            : 
     268                 :            : int
     269                 :      43241 : nvme_fabric_ctrlr_get_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
     270                 :            :                                   spdk_nvme_reg_cb cb_fn, void *cb_arg)
     271                 :            : {
     272                 :      43241 :         return nvme_fabric_prop_get_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, cb_fn, cb_arg);
     273                 :            : }
     274                 :            : 
     275                 :            : int
     276                 :       1148 : nvme_fabric_ctrlr_get_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
     277                 :            :                                   spdk_nvme_reg_cb cb_fn, void *cb_arg)
     278                 :            : {
     279                 :       1148 :         return nvme_fabric_prop_get_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, cb_fn, cb_arg);
     280                 :            : }
     281                 :            : 
     282                 :            : static void
     283                 :        142 : nvme_fabric_discover_probe(struct spdk_nvmf_discovery_log_page_entry *entry,
     284                 :            :                            struct spdk_nvme_probe_ctx *probe_ctx,
     285                 :            :                            int discover_priority)
     286                 :            : {
     287                 :         12 :         struct spdk_nvme_transport_id trid;
     288                 :            :         uint8_t *end;
     289                 :            :         size_t len;
     290                 :            : 
     291                 :        142 :         memset(&trid, 0, sizeof(trid));
     292                 :            : 
     293         [ +  + ]:        142 :         if (entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT ||
     294         [ -  + ]:         76 :             entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY) {
     295                 :         66 :                 SPDK_WARNLOG("Skipping unsupported current discovery service or"
     296                 :            :                              " discovery service referral\n");
     297                 :         66 :                 return;
     298         [ -  + ]:         76 :         } else if (entry->subtype != SPDK_NVMF_SUBTYPE_NVME) {
     299                 :          0 :                 SPDK_WARNLOG("Skipping unknown subtype %u\n", entry->subtype);
     300                 :          0 :                 return;
     301                 :            :         }
     302                 :            : 
     303                 :         76 :         trid.trtype = entry->trtype;
     304                 :         76 :         spdk_nvme_transport_id_populate_trstring(&trid, spdk_nvme_transport_id_trtype_str(entry->trtype));
     305         [ -  + ]:         76 :         if (!spdk_nvme_transport_available_by_name(trid.trstring)) {
     306                 :          0 :                 SPDK_WARNLOG("NVMe transport type %u not available; skipping probe\n",
     307                 :            :                              trid.trtype);
     308                 :          0 :                 return;
     309                 :            :         }
     310                 :            : 
     311                 :         76 :         trid.adrfam = entry->adrfam;
     312                 :            : 
     313                 :            :         /* Ensure that subnqn is null terminated. */
     314         [ -  + ]:         76 :         end = memchr(entry->subnqn, '\0', SPDK_NVMF_NQN_MAX_LEN + 1);
     315         [ -  + ]:         76 :         if (!end) {
     316                 :          0 :                 SPDK_ERRLOG("Discovery entry SUBNQN is not null terminated\n");
     317                 :          0 :                 return;
     318                 :            :         }
     319                 :         76 :         len = end - entry->subnqn;
     320         [ -  + ]:         76 :         memcpy(trid.subnqn, entry->subnqn, len);
     321                 :         76 :         trid.subnqn[len] = '\0';
     322                 :            : 
     323                 :            :         /* Convert traddr to a null terminated string. */
     324                 :         76 :         len = spdk_strlen_pad(entry->traddr, sizeof(entry->traddr), ' ');
     325         [ -  + ]:         76 :         memcpy(trid.traddr, entry->traddr, len);
     326         [ -  + ]:         76 :         if (spdk_str_chomp(trid.traddr) != 0) {
     327   [ #  #  #  # ]:          0 :                 SPDK_DEBUGLOG(nvme, "Trailing newlines removed from discovery TRADDR\n");
     328                 :            :         }
     329                 :            : 
     330                 :            :         /* Convert trsvcid to a null terminated string. */
     331                 :         76 :         len = spdk_strlen_pad(entry->trsvcid, sizeof(entry->trsvcid), ' ');
     332         [ -  + ]:         76 :         memcpy(trid.trsvcid, entry->trsvcid, len);
     333         [ -  + ]:         76 :         if (spdk_str_chomp(trid.trsvcid) != 0) {
     334   [ #  #  #  # ]:          0 :                 SPDK_DEBUGLOG(nvme, "Trailing newlines removed from discovery TRSVCID\n");
     335                 :            :         }
     336                 :            : 
     337   [ -  +  -  + ]:         76 :         SPDK_DEBUGLOG(nvme, "subnqn=%s, trtype=%u, traddr=%s, trsvcid=%s\n",
     338                 :            :                       trid.subnqn, trid.trtype,
     339                 :            :                       trid.traddr, trid.trsvcid);
     340                 :            : 
     341                 :            :         /* Copy the priority from the discovery ctrlr */
     342                 :         76 :         trid.priority = discover_priority;
     343                 :            : 
     344                 :         76 :         nvme_ctrlr_probe(&trid, probe_ctx, NULL);
     345                 :            : }
     346                 :            : 
     347                 :            : static int
     348                 :         86 : nvme_fabric_get_discovery_log_page(struct spdk_nvme_ctrlr *ctrlr,
     349                 :            :                                    void *log_page, uint32_t size, uint64_t offset)
     350                 :            : {
     351                 :            :         struct nvme_completion_poll_status *status;
     352                 :            :         int rc;
     353                 :            : 
     354                 :         86 :         status = calloc(1, sizeof(*status));
     355         [ -  + ]:         86 :         if (!status) {
     356                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     357                 :          0 :                 return -ENOMEM;
     358                 :            :         }
     359                 :            : 
     360                 :         86 :         rc = spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_DISCOVERY, 0, log_page, size, offset,
     361                 :            :                                               nvme_completion_poll_cb, status);
     362         [ +  + ]:         86 :         if (rc < 0) {
     363                 :         10 :                 free(status);
     364                 :         10 :                 return -1;
     365                 :            :         }
     366                 :            : 
     367         [ -  + ]:         76 :         if (nvme_wait_for_completion(ctrlr->adminq, status)) {
     368   [ #  #  #  # ]:          0 :                 if (!status->timed_out) {
     369                 :          0 :                         free(status);
     370                 :            :                 }
     371                 :          0 :                 return -1;
     372                 :            :         }
     373                 :         76 :         free(status);
     374                 :            : 
     375                 :         76 :         return 0;
     376                 :            : }
     377                 :            : 
     378                 :            : int
     379                 :       1100 : nvme_fabric_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,
     380                 :            :                        bool direct_connect)
     381                 :            : {
     382                 :         49 :         struct spdk_nvme_ctrlr_opts discovery_opts;
     383                 :            :         struct spdk_nvme_ctrlr *discovery_ctrlr;
     384                 :            :         int rc;
     385                 :            :         struct nvme_completion_poll_status *status;
     386                 :            : 
     387   [ -  +  +  + ]:       1100 :         if (strcmp(probe_ctx->trid.subnqn, SPDK_NVMF_DISCOVERY_NQN) != 0) {
     388                 :            :                 /* It is not a discovery_ctrlr info and try to directly connect it */
     389                 :        982 :                 rc = nvme_ctrlr_probe(&probe_ctx->trid, probe_ctx, NULL);
     390                 :        982 :                 return rc;
     391                 :            :         }
     392                 :            : 
     393                 :        118 :         spdk_nvme_ctrlr_get_default_ctrlr_opts(&discovery_opts, sizeof(discovery_opts));
     394   [ +  +  +  - ]:        118 :         if (direct_connect && probe_ctx->probe_cb) {
     395                 :         46 :                 probe_ctx->probe_cb(probe_ctx->cb_ctx, &probe_ctx->trid, &discovery_opts);
     396                 :            :         }
     397                 :            : 
     398                 :        118 :         discovery_ctrlr = nvme_transport_ctrlr_construct(&probe_ctx->trid, &discovery_opts, NULL);
     399         [ +  + ]:        118 :         if (discovery_ctrlr == NULL) {
     400                 :         11 :                 return -1;
     401                 :            :         }
     402                 :            : 
     403         [ +  + ]:     839647 :         while (discovery_ctrlr->state != NVME_CTRLR_STATE_READY) {
     404         [ +  + ]:     839541 :                 if (nvme_ctrlr_process_init(discovery_ctrlr) != 0) {
     405                 :          1 :                         nvme_ctrlr_destruct(discovery_ctrlr);
     406                 :          1 :                         return -1;
     407                 :            :                 }
     408                 :            :         }
     409                 :            : 
     410                 :        106 :         status = calloc(1, sizeof(*status));
     411         [ -  + ]:        106 :         if (!status) {
     412                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     413                 :          0 :                 nvme_ctrlr_destruct(discovery_ctrlr);
     414                 :          0 :                 return -ENOMEM;
     415                 :            :         }
     416                 :            : 
     417                 :            :         /* get the cdata info */
     418                 :        106 :         rc = nvme_ctrlr_cmd_identify(discovery_ctrlr, SPDK_NVME_IDENTIFY_CTRLR, 0, 0, 0,
     419                 :        106 :                                      &discovery_ctrlr->cdata, sizeof(discovery_ctrlr->cdata),
     420                 :            :                                      nvme_completion_poll_cb, status);
     421         [ -  + ]:        106 :         if (rc != 0) {
     422                 :          0 :                 SPDK_ERRLOG("Failed to identify cdata\n");
     423                 :          0 :                 nvme_ctrlr_destruct(discovery_ctrlr);
     424                 :          0 :                 free(status);
     425                 :          0 :                 return rc;
     426                 :            :         }
     427                 :            : 
     428         [ -  + ]:        106 :         if (nvme_wait_for_completion(discovery_ctrlr->adminq, status)) {
     429                 :          0 :                 SPDK_ERRLOG("nvme_identify_controller failed!\n");
     430                 :          0 :                 nvme_ctrlr_destruct(discovery_ctrlr);
     431   [ #  #  #  # ]:          0 :                 if (!status->timed_out) {
     432                 :          0 :                         free(status);
     433                 :            :                 }
     434                 :          0 :                 return -ENXIO;
     435                 :            :         }
     436                 :            : 
     437                 :        106 :         free(status);
     438                 :            : 
     439                 :            :         /* Direct attach through spdk_nvme_connect() API */
     440         [ +  + ]:        106 :         if (direct_connect == true) {
     441                 :            :                 /* Set the ready state to skip the normal init process */
     442                 :         35 :                 discovery_ctrlr->state = NVME_CTRLR_STATE_READY;
     443                 :         35 :                 nvme_ctrlr_connected(probe_ctx, discovery_ctrlr);
     444                 :         35 :                 nvme_ctrlr_add_process(discovery_ctrlr, 0);
     445                 :         35 :                 return 0;
     446                 :            :         }
     447                 :            : 
     448                 :         71 :         rc = nvme_fabric_ctrlr_discover(discovery_ctrlr, probe_ctx);
     449                 :         71 :         nvme_ctrlr_destruct(discovery_ctrlr);
     450                 :         71 :         return rc;
     451                 :            : }
     452                 :            : 
     453                 :            : int
     454                 :         71 : nvme_fabric_ctrlr_discover(struct spdk_nvme_ctrlr *ctrlr,
     455                 :            :                            struct spdk_nvme_probe_ctx *probe_ctx)
     456                 :            : {
     457                 :            :         struct spdk_nvmf_discovery_log_page *log_page;
     458                 :            :         struct spdk_nvmf_discovery_log_page_entry *log_page_entry;
     459                 :          0 :         char buffer[4096];
     460                 :            :         int rc;
     461                 :         71 :         uint64_t i, numrec, buffer_max_entries_first, buffer_max_entries, log_page_offset = 0;
     462                 :         71 :         uint64_t remaining_num_rec = 0;
     463                 :            :         uint16_t recfmt;
     464                 :            : 
     465         [ -  + ]:         71 :         memset(buffer, 0x0, 4096);
     466                 :         71 :         buffer_max_entries_first = (sizeof(buffer) - offsetof(struct spdk_nvmf_discovery_log_page,
     467                 :            :                                     entries[0])) /
     468                 :            :                                    sizeof(struct spdk_nvmf_discovery_log_page_entry);
     469                 :         71 :         buffer_max_entries = sizeof(buffer) / sizeof(struct spdk_nvmf_discovery_log_page_entry);
     470                 :            :         do {
     471                 :         71 :                 rc = nvme_fabric_get_discovery_log_page(ctrlr, buffer, sizeof(buffer), log_page_offset);
     472         [ -  + ]:         71 :                 if (rc < 0) {
     473   [ #  #  #  # ]:          0 :                         SPDK_DEBUGLOG(nvme, "Get Log Page - Discovery error\n");
     474                 :          0 :                         return rc;
     475                 :            :                 }
     476                 :            : 
     477         [ +  - ]:         71 :                 if (!remaining_num_rec) {
     478                 :         71 :                         log_page = (struct spdk_nvmf_discovery_log_page *)buffer;
     479                 :         71 :                         recfmt = from_le16(&log_page->recfmt);
     480         [ -  + ]:         71 :                         if (recfmt != 0) {
     481                 :          0 :                                 SPDK_ERRLOG("Unrecognized discovery log record format %" PRIu16 "\n", recfmt);
     482                 :          0 :                                 return -EPROTO;
     483                 :            :                         }
     484                 :         71 :                         remaining_num_rec = log_page->numrec;
     485                 :         71 :                         log_page_offset = offsetof(struct spdk_nvmf_discovery_log_page, entries[0]);
     486                 :         71 :                         log_page_entry = &log_page->entries[0];
     487                 :         71 :                         numrec = spdk_min(remaining_num_rec, buffer_max_entries_first);
     488                 :            :                 } else {
     489                 :          0 :                         numrec = spdk_min(remaining_num_rec, buffer_max_entries);
     490                 :          0 :                         log_page_entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
     491                 :            :                 }
     492                 :            : 
     493         [ +  + ]:        198 :                 for (i = 0; i < numrec; i++) {
     494                 :        127 :                         nvme_fabric_discover_probe(log_page_entry++, probe_ctx, ctrlr->trid.priority);
     495                 :            :                 }
     496                 :         71 :                 remaining_num_rec -= numrec;
     497                 :         71 :                 log_page_offset += numrec * sizeof(struct spdk_nvmf_discovery_log_page_entry);
     498         [ -  + ]:         71 :         } while (remaining_num_rec != 0);
     499                 :            : 
     500                 :         71 :         return 0;
     501                 :            : }
     502                 :            : 
     503                 :            : int
     504                 :       3419 : nvme_fabric_qpair_connect_async(struct spdk_nvme_qpair *qpair, uint32_t num_entries)
     505                 :            : {
     506                 :            :         struct nvme_completion_poll_status *status;
     507                 :        115 :         struct spdk_nvmf_fabric_connect_cmd cmd;
     508                 :            :         struct spdk_nvmf_fabric_connect_data *nvmf_data;
     509                 :            :         struct spdk_nvme_ctrlr *ctrlr;
     510                 :            :         struct nvme_request *req;
     511                 :            :         int rc;
     512                 :            : 
     513   [ +  +  -  + ]:       3419 :         if (num_entries == 0 || num_entries > SPDK_NVME_IO_QUEUE_MAX_ENTRIES) {
     514                 :          5 :                 return -EINVAL;
     515                 :            :         }
     516                 :            : 
     517                 :       3414 :         ctrlr = qpair->ctrlr;
     518         [ -  + ]:       3414 :         if (!ctrlr) {
     519                 :          0 :                 return -EINVAL;
     520                 :            :         }
     521                 :            : 
     522                 :       3414 :         nvmf_data = spdk_zmalloc(sizeof(*nvmf_data), 0, NULL,
     523                 :            :                                  SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
     524         [ -  + ]:       3414 :         if (!nvmf_data) {
     525                 :          0 :                 SPDK_ERRLOG("nvmf_data allocation error\n");
     526                 :          0 :                 return -ENOMEM;
     527                 :            :         }
     528                 :            : 
     529                 :       3414 :         status = calloc(1, sizeof(*status));
     530         [ -  + ]:       3414 :         if (!status) {
     531                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     532                 :          0 :                 spdk_free(nvmf_data);
     533                 :          0 :                 return -ENOMEM;
     534                 :            :         }
     535                 :            : 
     536                 :       3414 :         status->dma_data = nvmf_data;
     537                 :            : 
     538         [ -  + ]:       3414 :         memset(&cmd, 0, sizeof(cmd));
     539                 :       3414 :         cmd.opcode = SPDK_NVME_OPC_FABRIC;
     540                 :       3414 :         cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT;
     541                 :       3414 :         cmd.qid = qpair->id;
     542                 :       3414 :         cmd.sqsize = num_entries - 1;
     543                 :       3414 :         cmd.kato = ctrlr->opts.keep_alive_timeout_ms;
     544                 :            : 
     545         [ -  + ]:       3414 :         assert(qpair->reserved_req != NULL);
     546                 :       3414 :         req = qpair->reserved_req;
     547                 :       3414 :         NVME_INIT_REQUEST(req, nvme_completion_poll_cb, status, NVME_PAYLOAD_CONTIG(nvmf_data, NULL),
     548                 :            :                           sizeof(*nvmf_data), 0);
     549                 :            : 
     550                 :       3414 :         memcpy(&req->cmd, &cmd, sizeof(cmd));
     551                 :            : 
     552         [ +  + ]:       3414 :         if (nvme_qpair_is_admin_queue(qpair)) {
     553                 :       1185 :                 nvmf_data->cntlid = 0xFFFF;
     554                 :            :         } else {
     555                 :       2229 :                 nvmf_data->cntlid = ctrlr->cntlid;
     556                 :            :         }
     557                 :            : 
     558                 :            :         SPDK_STATIC_ASSERT(sizeof(nvmf_data->hostid) == sizeof(ctrlr->opts.extended_host_id),
     559                 :            :                            "host ID size mismatch");
     560                 :       3414 :         memcpy(nvmf_data->hostid, ctrlr->opts.extended_host_id, sizeof(nvmf_data->hostid));
     561         [ -  + ]:       3414 :         snprintf(nvmf_data->hostnqn, sizeof(nvmf_data->hostnqn), "%s", ctrlr->opts.hostnqn);
     562         [ -  + ]:       3414 :         snprintf(nvmf_data->subnqn, sizeof(nvmf_data->subnqn), "%s", ctrlr->trid.subnqn);
     563                 :            : 
     564                 :       3414 :         rc = nvme_qpair_submit_request(qpair, req);
     565         [ -  + ]:       3414 :         if (rc < 0) {
     566                 :          0 :                 SPDK_ERRLOG("Failed to allocate/submit FABRIC_CONNECT command, rc %d\n", rc);
     567                 :          0 :                 spdk_free(status->dma_data);
     568                 :          0 :                 free(status);
     569                 :          0 :                 return rc;
     570                 :            :         }
     571                 :            : 
     572                 :            :         /* If we time out, the qpair will abort the request upon destruction. */
     573         [ -  + ]:       3414 :         if (ctrlr->opts.fabrics_connect_timeout_us > 0) {
     574                 :          0 :                 status->timeout_tsc = spdk_get_ticks() + ctrlr->opts.fabrics_connect_timeout_us *
     575                 :          0 :                                       spdk_get_ticks_hz() / SPDK_SEC_TO_USEC;
     576                 :            :         }
     577                 :            : 
     578                 :       3414 :         qpair->auth.flags = 0;
     579                 :       3414 :         qpair->connect_state = NVME_QPAIR_CONNECT_STATE_CONNECTING;
     580                 :       3414 :         qpair->poll_status = status;
     581                 :       3414 :         return 0;
     582                 :            : }
     583                 :            : 
     584                 :            : static int
     585                 :     257365 : _nvme_fabric_qpair_connect_poll(struct spdk_nvme_qpair *qpair)
     586                 :            : {
     587                 :            :         struct nvme_completion_poll_status *status;
     588                 :            :         struct spdk_nvmf_fabric_connect_rsp *rsp;
     589                 :            :         struct spdk_nvme_ctrlr *ctrlr;
     590                 :     257365 :         int rc = 0;
     591                 :            : 
     592                 :     257365 :         ctrlr = qpair->ctrlr;
     593                 :     257365 :         status = qpair->poll_status;
     594                 :            : 
     595         [ +  + ]:     257365 :         if (nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL) == -EAGAIN) {
     596                 :     253951 :                 return -EAGAIN;
     597                 :            :         }
     598                 :            : 
     599   [ +  +  +  +  :       3414 :         if (status->timed_out || spdk_nvme_cpl_is_error(&status->cpl)) {
             +  +  -  + ]
     600   [ +  +  +  + ]:        208 :                 SPDK_ERRLOG("Connect command failed, rc %d, trtype:%s adrfam:%s "
     601                 :            :                             "traddr:%s trsvcid:%s subnqn:%s\n",
     602                 :            :                             status->timed_out ? -ECANCELED : -EIO,
     603                 :            :                             spdk_nvme_transport_id_trtype_str(ctrlr->trid.trtype),
     604                 :            :                             spdk_nvme_transport_id_adrfam_str(ctrlr->trid.adrfam),
     605                 :            :                             ctrlr->trid.traddr,
     606                 :            :                             ctrlr->trid.trsvcid,
     607                 :            :                             ctrlr->trid.subnqn);
     608   [ +  +  +  + ]:        208 :                 if (status->timed_out) {
     609                 :          5 :                         rc = -ECANCELED;
     610                 :            :                 } else {
     611                 :        203 :                         SPDK_ERRLOG("Connect command completed with error: sct %d, sc %d\n",
     612                 :            :                                     status->cpl.status.sct, status->cpl.status.sc);
     613                 :        203 :                         rc = -EIO;
     614                 :            :                 }
     615                 :            : 
     616                 :        208 :                 goto finish;
     617                 :            :         }
     618                 :            : 
     619                 :       3206 :         rsp = (struct spdk_nvmf_fabric_connect_rsp *)&status->cpl;
     620         [ +  + ]:       3206 :         if (nvme_qpair_is_admin_queue(qpair)) {
     621                 :       1180 :                 ctrlr->cntlid = rsp->status_code_specific.success.cntlid;
     622   [ -  +  +  + ]:       1180 :                 SPDK_DEBUGLOG(nvme, "CNTLID 0x%04" PRIx16 "\n", ctrlr->cntlid);
     623                 :            :         }
     624         [ +  + ]:       3206 :         if (rsp->status_code_specific.success.authreq.atr) {
     625                 :        702 :                 qpair->auth.flags |= NVME_QPAIR_AUTH_FLAG_ATR;
     626                 :            :         }
     627         [ +  - ]:       3206 :         if (rsp->status_code_specific.success.authreq.ascr) {
     628                 :          0 :                 qpair->auth.flags |= NVME_QPAIR_AUTH_FLAG_ASCR;
     629                 :            :         }
     630                 :       3206 : finish:
     631                 :       3414 :         qpair->poll_status = NULL;
     632   [ +  +  +  + ]:       3414 :         if (!status->timed_out) {
     633                 :       3409 :                 spdk_free(status->dma_data);
     634                 :       3409 :                 free(status);
     635                 :            :         }
     636                 :            : 
     637                 :       3414 :         return rc;
     638                 :            : }
     639                 :            : 
     640                 :            : int
     641                 :    1339369 : nvme_fabric_qpair_connect_poll(struct spdk_nvme_qpair *qpair)
     642                 :            : {
     643                 :    1339369 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     644                 :            :         int rc;
     645                 :            : 
     646      [ +  +  - ]:    1339369 :         switch (qpair->connect_state) {
     647                 :     257365 :         case NVME_QPAIR_CONNECT_STATE_CONNECTING:
     648                 :     257365 :                 rc = _nvme_fabric_qpair_connect_poll(qpair);
     649         [ +  + ]:     257365 :                 if (rc != 0) {
     650                 :     254159 :                         break;
     651                 :            :                 }
     652         [ +  + ]:       3206 :                 if (qpair->auth.flags & (NVME_QPAIR_AUTH_FLAG_ATR | NVME_QPAIR_AUTH_FLAG_ASCR) ||
     653         [ +  + ]:       2504 :                     ctrlr->opts.dhchap_ctrlr_key != NULL) {
     654                 :        705 :                         rc = nvme_fabric_qpair_authenticate_async(qpair);
     655         [ +  + ]:        705 :                         if (rc == 0) {
     656                 :        698 :                                 qpair->connect_state = NVME_QPAIR_CONNECT_STATE_AUTHENTICATING;
     657                 :        698 :                                 rc = -EAGAIN;
     658                 :            :                         }
     659                 :        705 :                         break;
     660                 :            :                 }
     661                 :       2501 :                 qpair->connect_state = NVME_QPAIR_CONNECT_STATE_CONNECTED;
     662                 :       2501 :                 break;
     663                 :    1082004 :         case NVME_QPAIR_CONNECT_STATE_AUTHENTICATING:
     664                 :    1082004 :                 rc = nvme_fabric_qpair_authenticate_poll(qpair);
     665         [ +  + ]:    1082004 :                 if (rc == 0) {
     666                 :        678 :                         qpair->connect_state = NVME_QPAIR_CONNECT_STATE_CONNECTED;
     667                 :            :                 }
     668                 :    1082004 :                 break;
     669                 :            :         /* Once qpair is connected or a failure occurs, users mustn't call this function anymore */
     670                 :          0 :         case NVME_QPAIR_CONNECT_STATE_CONNECTED:
     671                 :            :         case NVME_QPAIR_CONNECT_STATE_FAILED:
     672                 :            :         default:
     673                 :          0 :                 assert(0 && "invalid state");
     674                 :            :                 rc = -EINVAL;
     675                 :            :                 break;
     676                 :            :         }
     677                 :            : 
     678   [ +  +  +  + ]:    1339369 :         if (rc != 0 && rc != -EAGAIN) {
     679                 :        235 :                 qpair->connect_state = NVME_QPAIR_CONNECT_STATE_FAILED;
     680                 :            :         }
     681                 :            : 
     682                 :    1339369 :         return rc;
     683                 :            : }
     684                 :            : 
     685                 :            : int
     686                 :         20 : nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries)
     687                 :            : {
     688                 :            :         int rc;
     689                 :            : 
     690                 :         20 :         rc = nvme_fabric_qpair_connect_async(qpair, num_entries);
     691         [ +  + ]:         20 :         if (rc) {
     692                 :          5 :                 return rc;
     693                 :            :         }
     694                 :            : 
     695                 :            :         do {
     696                 :            :                 /* Wait until the command completes or times out */
     697                 :         15 :                 rc = nvme_fabric_qpair_connect_poll(qpair);
     698         [ -  + ]:         15 :         } while (rc == -EAGAIN);
     699                 :            : 
     700                 :         15 :         return rc;
     701                 :            : }

Generated by: LCOV version 1.14