LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_fabric.c (source / functions) Hit Total Coverage
Test: Combined Lines: 271 366 74.0 %
Date: 2024-12-12 21:49:58 Functions: 20 24 83.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 300 783 38.3 %

           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                 :       4820 : 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                 :       4820 :         struct spdk_nvmf_fabric_prop_set_cmd cmd = {};
      29                 :            : 
      30   [ +  +  +  +  :       4820 :         assert(size == SPDK_NVMF_PROP_SIZE_4 || size == SPDK_NVMF_PROP_SIZE_8);
                   #  # ]
      31                 :            : 
      32                 :       4820 :         cmd.opcode = SPDK_NVME_OPC_FABRIC;
      33                 :       4820 :         cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_SET;
      34                 :       4820 :         cmd.ofst = offset;
      35                 :       4820 :         cmd.attrib.size = size;
      36         [ +  - ]:       4820 :         cmd.value.u64 = value;
      37                 :            : 
      38                 :       6501 :         return spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, (struct spdk_nvme_cmd *)&cmd,
      39                 :       1681 :                                              NULL, 0, cb_fn, cb_arg);
      40                 :            : }
      41                 :            : 
      42                 :            : static int
      43                 :          4 : 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                 :          4 :         status = calloc(1, sizeof(*status));
      50         [ +  + ]:          4 :         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                 :          1 :                                       nvme_completion_poll_cb, status);
      57         [ +  + ]:          4 :         if (rc < 0) {
      58                 :          0 :                 free(status);
      59                 :          0 :                 return rc;
      60                 :            :         }
      61                 :            : 
      62   [ -  +  #  #  :          4 :         if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
             #  #  #  # ]
      63   [ #  #  #  #  :          0 :                 if (!status->timed_out) {
             #  #  #  # ]
      64                 :          0 :                         free(status);
      65                 :          0 :                 }
      66                 :          0 :                 SPDK_ERRLOG("Property Set failed\n");
      67                 :          0 :                 return -1;
      68                 :            :         }
      69                 :          4 :         free(status);
      70                 :            : 
      71                 :          4 :         return 0;
      72                 :          1 : }
      73                 :            : 
      74                 :            : static void
      75                 :       4816 : nvme_fabric_prop_set_cmd_done(void *ctx, const struct spdk_nvme_cpl *cpl)
      76                 :            : {
      77                 :       4816 :         struct nvme_fabric_prop_ctx *prop_ctx = ctx;
      78                 :            : 
      79   [ +  -  +  -  :       4816 :         prop_ctx->cb_fn(prop_ctx->cb_arg, prop_ctx->value, cpl);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      80                 :       4816 :         free(prop_ctx);
      81                 :       4816 : }
      82                 :            : 
      83                 :            : static int
      84                 :       4816 : 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                 :       4816 :         ctx = calloc(1, sizeof(*ctx));
      92         [ +  + ]:       4816 :         if (ctx == NULL) {
      93                 :          0 :                 SPDK_ERRLOG("Failed to allocate fabrics property context\n");
      94                 :          0 :                 return -ENOMEM;
      95                 :            :         }
      96                 :            : 
      97   [ +  -  +  - ]:       4816 :         ctx->value = value;
      98   [ +  -  +  - ]:       4816 :         ctx->cb_fn = cb_fn;
      99   [ +  -  +  - ]:       4816 :         ctx->cb_arg = cb_arg;
     100                 :            : 
     101                 :       6496 :         rc = nvme_fabric_prop_set_cmd(ctrlr, offset, size, value,
     102                 :       1680 :                                       nvme_fabric_prop_set_cmd_done, ctx);
     103         [ +  + ]:       4816 :         if (rc != 0) {
     104                 :          0 :                 SPDK_ERRLOG("Failed to send Property Set fabrics command\n");
     105                 :          0 :                 free(ctx);
     106                 :          0 :         }
     107                 :            : 
     108                 :       4816 :         return rc;
     109                 :       1680 : }
     110                 :            : 
     111                 :            : static int
     112                 :      99917 : 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                 :      99917 :         struct spdk_nvmf_fabric_prop_set_cmd cmd = {};
     116                 :            : 
     117   [ +  +  +  +  :      99917 :         assert(size == SPDK_NVMF_PROP_SIZE_4 || size == SPDK_NVMF_PROP_SIZE_8);
                   #  # ]
     118                 :            : 
     119                 :      99917 :         cmd.opcode = SPDK_NVME_OPC_FABRIC;
     120                 :      99917 :         cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET;
     121                 :      99917 :         cmd.ofst = offset;
     122                 :      99917 :         cmd.attrib.size = size;
     123                 :            : 
     124                 :     105799 :         return spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, (struct spdk_nvme_cmd *)&cmd,
     125                 :       5882 :                                              NULL, 0, cb_fn, cb_arg);
     126                 :            : }
     127                 :            : 
     128                 :            : static int
     129                 :       1698 : 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                 :       1698 :         status = calloc(1, sizeof(*status));
     137         [ +  + ]:       1698 :         if (!status) {
     138                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     139                 :          0 :                 return -ENOMEM;
     140                 :            :         }
     141                 :            : 
     142                 :       1698 :         rc = nvme_fabric_prop_get_cmd(ctrlr, offset, size, nvme_completion_poll_cb, status);
     143         [ +  + ]:       1698 :         if (rc < 0) {
     144                 :          0 :                 free(status);
     145                 :          0 :                 return rc;
     146                 :            :         }
     147                 :            : 
     148   [ -  +  #  #  :       1698 :         if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
             #  #  #  # ]
     149   [ #  #  #  #  :          0 :                 if (!status->timed_out) {
             #  #  #  # ]
     150                 :          0 :                         free(status);
     151                 :          0 :                 }
     152                 :          0 :                 SPDK_ERRLOG("Property Get failed, offset %x, size %u\n", offset, size);
     153                 :          0 :                 return -1;
     154                 :            :         }
     155                 :            : 
     156         [ #  # ]:       1698 :         response = (struct spdk_nvmf_fabric_prop_get_rsp *)&status->cpl;
     157                 :            : 
     158         [ +  + ]:       1698 :         if (size == SPDK_NVMF_PROP_SIZE_4) {
     159   [ #  #  #  #  :       1694 :                 *value = response->value.u32.low;
          #  #  #  #  #  
                      # ]
     160                 :          1 :         } else {
     161   [ #  #  #  #  :          4 :                 *value = response->value.u64;
             #  #  #  # ]
     162                 :            :         }
     163                 :            : 
     164                 :       1698 :         free(status);
     165                 :            : 
     166                 :       1698 :         return 0;
     167                 :          2 : }
     168                 :            : 
     169                 :            : static void
     170                 :      98216 : nvme_fabric_prop_get_cmd_done(void *ctx, const struct spdk_nvme_cpl *cpl)
     171                 :            : {
     172                 :      98216 :         struct nvme_fabric_prop_ctx *prop_ctx = ctx;
     173                 :            :         struct spdk_nvmf_fabric_prop_get_rsp *response;
     174                 :      98216 :         uint64_t value = 0;
     175                 :            : 
     176   [ +  -  +  -  :      98216 :         if (spdk_nvme_cpl_is_success(cpl)) {
          +  -  +  -  +  
          -  +  -  +  -  
                   -  + ]
     177                 :      98216 :                 response = (struct spdk_nvmf_fabric_prop_get_rsp *)cpl;
     178                 :            : 
     179   [ +  +  +  -  :      98216 :                 switch (prop_ctx->size) {
                +  -  + ]
     180                 :      90708 :                 case SPDK_NVMF_PROP_SIZE_4:
     181   [ +  -  +  -  :      95748 :                         value = response->value.u32.low;
             +  -  +  - ]
     182                 :      95748 :                         break;
     183                 :       1628 :                 case SPDK_NVMF_PROP_SIZE_8:
     184   [ +  -  +  -  :       2468 :                         value = response->value.u64;
                   +  - ]
     185                 :       2468 :                         break;
     186                 :          0 :                 default:
     187         [ #  # ]:          0 :                         assert(0 && "Should never happen");
     188                 :            :                 }
     189                 :       5880 :         }
     190                 :            : 
     191   [ +  -  +  -  :      98216 :         prop_ctx->cb_fn(prop_ctx->cb_arg, value, cpl);
          -  +  +  -  +  
                -  +  - ]
     192                 :      98216 :         free(prop_ctx);
     193                 :      98216 : }
     194                 :            : 
     195                 :            : static int
     196                 :      98219 : 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                 :      98219 :         ctx = calloc(1, sizeof(*ctx));
     203         [ +  + ]:      98219 :         if (ctx == NULL) {
     204                 :          0 :                 SPDK_ERRLOG("Failed to allocate fabrics property context\n");
     205                 :          0 :                 return -ENOMEM;
     206                 :            :         }
     207                 :            : 
     208   [ +  -  +  - ]:      98219 :         ctx->size = size;
     209   [ +  -  +  - ]:      98219 :         ctx->cb_fn = cb_fn;
     210   [ +  -  +  - ]:      98219 :         ctx->cb_arg = cb_arg;
     211                 :            : 
     212                 :      98219 :         rc = nvme_fabric_prop_get_cmd(ctrlr, offset, size, nvme_fabric_prop_get_cmd_done, ctx);
     213         [ +  + ]:      98219 :         if (rc != 0) {
     214                 :          3 :                 SPDK_ERRLOG("Failed to send Property Get fabrics command\n");
     215                 :          3 :                 free(ctx);
     216                 :          0 :         }
     217                 :            : 
     218                 :      98219 :         return rc;
     219                 :       5880 : }
     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                 :       1690 : 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                 :       1690 :         rc = nvme_fabric_prop_get_cmd_sync(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, &tmp_value);
     239                 :            : 
     240         [ +  - ]:       1690 :         if (!rc) {
     241         [ #  # ]:       1690 :                 *value = (uint32_t)tmp_value;
     242                 :          0 :         }
     243                 :       1690 :         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                 :       4816 : 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                 :       6496 :         return nvme_fabric_prop_set_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, value,
     257                 :       1680 :                                               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                 :          0 :                                               cb_fn, cb_arg);
     266                 :            : }
     267                 :            : 
     268                 :            : int
     269                 :      95751 : 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                 :      95751 :         return nvme_fabric_prop_get_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_4, cb_fn, cb_arg);
     273                 :            : }
     274                 :            : 
     275                 :            : int
     276                 :       2468 : 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                 :       2468 :         return nvme_fabric_prop_get_cmd_async(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, cb_fn, cb_arg);
     280                 :            : }
     281                 :            : 
     282                 :            : static void
     283                 :        159 : 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                 :          9 :         struct spdk_nvme_transport_id trid;
     288                 :            :         uint8_t *end;
     289                 :            :         size_t len;
     290                 :            : 
     291         [ #  # ]:        159 :         memset(&trid, 0, sizeof(trid));
     292                 :            : 
     293   [ +  +  -  +  :        159 :         if (entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT ||
             #  #  #  # ]
     294   [ -  +  #  # ]:         99 :             entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY) {
     295                 :         60 :                 SPDK_WARNLOG("Skipping unsupported current discovery service or"
     296                 :            :                              " discovery service referral\n");
     297                 :         60 :                 return;
     298   [ -  +  #  #  :         99 :         } 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   [ #  #  #  #  :         99 :         trid.trtype = entry->trtype;
                   #  # ]
     304   [ #  #  #  # ]:         99 :         spdk_nvme_transport_id_populate_trstring(&trid, spdk_nvme_transport_id_trtype_str(entry->trtype));
     305         [ +  + ]:         99 :         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   [ #  #  #  #  :         99 :         trid.adrfam = entry->adrfam;
                   #  # ]
     312                 :            : 
     313                 :            :         /* Ensure that subnqn is null terminated. */
     314   [ -  +  #  # ]:         99 :         end = memchr(entry->subnqn, '\0', SPDK_NVMF_NQN_MAX_LEN + 1);
     315         [ +  + ]:         99 :         if (!end) {
     316                 :          0 :                 SPDK_ERRLOG("Discovery entry SUBNQN is not null terminated\n");
     317                 :          0 :                 return;
     318                 :            :         }
     319         [ #  # ]:         99 :         len = end - entry->subnqn;
     320   [ -  +  #  #  :         99 :         memcpy(trid.subnqn, entry->subnqn, len);
                   #  # ]
     321   [ #  #  #  #  :         99 :         trid.subnqn[len] = '\0';
                   #  # ]
     322                 :            : 
     323                 :            :         /* Convert traddr to a null terminated string. */
     324         [ #  # ]:         99 :         len = spdk_strlen_pad(entry->traddr, sizeof(entry->traddr), ' ');
     325   [ -  +  #  #  :         99 :         memcpy(trid.traddr, entry->traddr, len);
                   #  # ]
     326         [ +  + ]:         99 :         if (spdk_str_chomp(trid.traddr) != 0) {
     327   [ #  #  #  #  :          0 :                 SPDK_DEBUGLOG(nvme, "Trailing newlines removed from discovery TRADDR\n");
                   #  # ]
     328                 :          0 :         }
     329                 :            : 
     330                 :            :         /* Convert trsvcid to a null terminated string. */
     331         [ #  # ]:         99 :         len = spdk_strlen_pad(entry->trsvcid, sizeof(entry->trsvcid), ' ');
     332   [ -  +  #  #  :         99 :         memcpy(trid.trsvcid, entry->trsvcid, len);
                   #  # ]
     333         [ +  + ]:         99 :         if (spdk_str_chomp(trid.trsvcid) != 0) {
     334   [ #  #  #  #  :          0 :                 SPDK_DEBUGLOG(nvme, "Trailing newlines removed from discovery TRSVCID\n");
                   #  # ]
     335                 :          0 :         }
     336                 :            : 
     337   [ +  +  -  +  :         99 :         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         [ #  # ]:         99 :         trid.priority = discover_priority;
     343                 :            : 
     344                 :         99 :         nvme_ctrlr_probe(&trid, probe_ctx, NULL);
     345                 :          3 : }
     346                 :            : 
     347                 :            : static int
     348                 :         93 : 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                 :         93 :         status = calloc(1, sizeof(*status));
     355         [ +  + ]:         93 :         if (!status) {
     356                 :          0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     357                 :          0 :                 return -ENOMEM;
     358                 :            :         }
     359                 :            : 
     360                 :         96 :         rc = spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_DISCOVERY, 0, log_page, size, offset,
     361                 :          3 :                                               nvme_completion_poll_cb, status);
     362         [ +  + ]:         93 :         if (rc < 0) {
     363                 :          8 :                 free(status);
     364                 :          8 :                 return -1;
     365                 :            :         }
     366                 :            : 
     367   [ -  +  #  #  :         85 :         if (nvme_wait_for_completion(ctrlr->adminq, status)) {
                   #  # ]
     368   [ #  #  #  #  :          0 :                 if (!status->timed_out) {
             #  #  #  # ]
     369                 :          0 :                         free(status);
     370                 :          0 :                 }
     371                 :          0 :                 return -1;
     372                 :            :         }
     373                 :         85 :         free(status);
     374                 :            : 
     375                 :         85 :         return 0;
     376                 :          3 : }
     377                 :            : 
     378                 :            : int
     379                 :       2403 : nvme_fabric_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,
     380                 :            :                        bool direct_connect)
     381                 :            : {
     382                 :         47 :         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   [ +  +  +  +  :       2403 :         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         [ +  - ]:       2270 :                 rc = nvme_ctrlr_probe(&probe_ctx->trid, probe_ctx, NULL);
     390                 :       2270 :                 return rc;
     391                 :            :         }
     392                 :            : 
     393                 :        133 :         spdk_nvme_ctrlr_get_default_ctrlr_opts(&discovery_opts, sizeof(discovery_opts));
     394   [ +  +  +  -  :        133 :         if (direct_connect && probe_ctx->probe_cb) {
          #  #  #  #  #  
                      # ]
     395   [ #  #  #  #  :         54 :                 probe_ctx->probe_cb(probe_ctx->cb_ctx, &probe_ctx->trid, &discovery_opts);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     396                 :          0 :         }
     397                 :            : 
     398         [ #  # ]:        133 :         discovery_ctrlr = nvme_transport_ctrlr_construct(&probe_ctx->trid, &discovery_opts, NULL);
     399         [ +  + ]:        133 :         if (discovery_ctrlr == NULL) {
     400                 :         14 :                 return -1;
     401                 :            :         }
     402                 :            : 
     403   [ +  +  #  #  :    1081629 :         while (discovery_ctrlr->state != NVME_CTRLR_STATE_READY) {
                   #  # ]
     404         [ +  + ]:    1081511 :                 if (nvme_ctrlr_process_init(discovery_ctrlr) != 0) {
     405                 :          1 :                         nvme_ctrlr_destruct(discovery_ctrlr);
     406                 :          1 :                         return -1;
     407                 :            :                 }
     408                 :            :         }
     409                 :            : 
     410                 :        118 :         status = calloc(1, sizeof(*status));
     411         [ -  + ]:        118 :         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                 :        118 :         rc = nvme_ctrlr_cmd_identify(discovery_ctrlr, SPDK_NVME_IDENTIFY_CTRLR, 0, 0, 0,
     419         [ #  # ]:        118 :                                      &discovery_ctrlr->cdata, sizeof(discovery_ctrlr->cdata),
     420                 :          0 :                                      nvme_completion_poll_cb, status);
     421         [ -  + ]:        118 :         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   [ -  +  #  #  :        118 :         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                 :          0 :                 }
     434                 :          0 :                 return -ENXIO;
     435                 :            :         }
     436                 :            : 
     437                 :        118 :         free(status);
     438                 :            : 
     439                 :            :         /* Direct attach through spdk_nvme_connect() API */
     440   [ +  +  #  # ]:        118 :         if (direct_connect == true) {
     441                 :            :                 /* Set the ready state to skip the normal init process */
     442   [ #  #  #  # ]:         41 :                 discovery_ctrlr->state = NVME_CTRLR_STATE_READY;
     443                 :         41 :                 nvme_ctrlr_connected(probe_ctx, discovery_ctrlr);
     444                 :         41 :                 nvme_ctrlr_add_process(discovery_ctrlr, 0);
     445                 :         41 :                 return 0;
     446                 :            :         }
     447                 :            : 
     448                 :         77 :         rc = nvme_fabric_ctrlr_discover(discovery_ctrlr, probe_ctx);
     449                 :         77 :         nvme_ctrlr_destruct(discovery_ctrlr);
     450                 :         77 :         return rc;
     451                 :        840 : }
     452                 :            : 
     453                 :            : int
     454                 :         77 : 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                 :         77 :         uint64_t i, numrec, buffer_max_entries_first, buffer_max_entries, log_page_offset = 0;
     462                 :         77 :         uint64_t remaining_num_rec = 0;
     463                 :            :         uint16_t recfmt;
     464                 :            : 
     465         [ -  + ]:         77 :         memset(buffer, 0x0, 4096);
     466                 :         77 :         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                 :         77 :         buffer_max_entries = sizeof(buffer) / sizeof(struct spdk_nvmf_discovery_log_page_entry);
     470                 :          0 :         do {
     471                 :         81 :                 rc = nvme_fabric_get_discovery_log_page(ctrlr, buffer, sizeof(buffer), log_page_offset);
     472         [ -  + ]:         81 :                 if (rc < 0) {
     473   [ #  #  #  #  :          0 :                         SPDK_DEBUGLOG(nvme, "Get Log Page - Discovery error\n");
                   #  # ]
     474                 :          0 :                         return rc;
     475                 :            :                 }
     476                 :            : 
     477         [ +  + ]:         81 :                 if (!remaining_num_rec) {
     478                 :         77 :                         log_page = (struct spdk_nvmf_discovery_log_page *)buffer;
     479         [ #  # ]:         77 :                         recfmt = from_le16(&log_page->recfmt);
     480         [ -  + ]:         77 :                         if (recfmt != 0) {
     481                 :          0 :                                 SPDK_ERRLOG("Unrecognized discovery log record format %" PRIu16 "\n", recfmt);
     482                 :          0 :                                 return -EPROTO;
     483                 :            :                         }
     484   [ #  #  #  # ]:         77 :                         remaining_num_rec = log_page->numrec;
     485                 :         77 :                         log_page_offset = offsetof(struct spdk_nvmf_discovery_log_page, entries[0]);
     486   [ #  #  #  # ]:         77 :                         log_page_entry = &log_page->entries[0];
     487         [ #  # ]:         77 :                         numrec = spdk_min(remaining_num_rec, buffer_max_entries_first);
     488                 :          0 :                 } else {
     489         [ #  # ]:          4 :                         numrec = spdk_min(remaining_num_rec, buffer_max_entries);
     490                 :          4 :                         log_page_entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
     491                 :            :                 }
     492                 :            : 
     493         [ +  + ]:        228 :                 for (i = 0; i < numrec; i++) {
     494   [ #  #  #  #  :        147 :                         nvme_fabric_discover_probe(log_page_entry++, probe_ctx, ctrlr->trid.priority);
             #  #  #  # ]
     495                 :          0 :                 }
     496                 :         81 :                 remaining_num_rec -= numrec;
     497                 :         81 :                 log_page_offset += numrec * sizeof(struct spdk_nvmf_discovery_log_page_entry);
     498         [ +  + ]:         81 :         } while (remaining_num_rec != 0);
     499                 :            : 
     500                 :         77 :         return 0;
     501                 :          0 : }
     502                 :            : 
     503                 :            : int
     504                 :       7312 : nvme_fabric_qpair_connect_async(struct spdk_nvme_qpair *qpair, uint32_t num_entries)
     505                 :            : {
     506                 :            :         struct nvme_completion_poll_status *status;
     507                 :        104 :         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   [ +  +  -  + ]:       7312 :         if (num_entries == 0 || num_entries > SPDK_NVME_IO_QUEUE_MAX_ENTRIES) {
     514                 :          4 :                 return -EINVAL;
     515                 :            :         }
     516                 :            : 
     517   [ +  -  +  - ]:       7308 :         ctrlr = qpair->ctrlr;
     518         [ +  + ]:       7308 :         if (!ctrlr) {
     519                 :          0 :                 return -EINVAL;
     520                 :            :         }
     521                 :            : 
     522                 :       7308 :         nvmf_data = spdk_zmalloc(sizeof(*nvmf_data), 0, NULL,
     523                 :            :                                  SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
     524         [ +  + ]:       7308 :         if (!nvmf_data) {
     525                 :          0 :                 SPDK_ERRLOG("nvmf_data allocation error\n");
     526                 :          0 :                 return -ENOMEM;
     527                 :            :         }
     528                 :            : 
     529                 :       7308 :         status = calloc(1, sizeof(*status));
     530         [ +  + ]:       7308 :         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   [ +  -  +  - ]:       7308 :         status->dma_data = nvmf_data;
     537                 :            : 
     538         [ +  + ]:       7308 :         memset(&cmd, 0, sizeof(cmd));
     539                 :       7308 :         cmd.opcode = SPDK_NVME_OPC_FABRIC;
     540                 :       7308 :         cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT;
     541   [ +  -  +  - ]:       7308 :         cmd.qid = qpair->id;
     542                 :       7308 :         cmd.sqsize = num_entries - 1;
     543   [ +  -  +  -  :       7308 :         cmd.kato = ctrlr->opts.keep_alive_timeout_ms;
                   +  - ]
     544                 :            : 
     545   [ +  +  +  -  :       7308 :         assert(qpair->reserved_req != NULL);
             +  -  #  # ]
     546   [ +  -  +  - ]:       7308 :         req = qpair->reserved_req;
     547   [ +  -  +  -  :       7308 :         NVME_INIT_REQUEST(req, nvme_completion_poll_cb, status, NVME_PAYLOAD_CONTIG(nvmf_data, NULL),
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     548                 :            :                           sizeof(*nvmf_data), 0);
     549                 :            : 
     550   [ +  -  +  -  :       7308 :         memcpy(&req->cmd, &cmd, sizeof(cmd));
                   +  - ]
     551                 :            : 
     552         [ +  + ]:       7308 :         if (nvme_qpair_is_admin_queue(qpair)) {
     553   [ +  -  +  - ]:       2533 :                 nvmf_data->cntlid = 0xFFFF;
     554                 :        842 :         } else {
     555   [ +  -  +  -  :       4775 :                 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   [ +  -  +  -  :       7308 :         memcpy(nvmf_data->hostid, ctrlr->opts.extended_host_id, sizeof(nvmf_data->hostid));
          +  -  +  -  +  
                      - ]
     561   [ +  +  +  -  :       7308 :         snprintf(nvmf_data->hostnqn, sizeof(nvmf_data->hostnqn), "%s", ctrlr->opts.hostnqn);
                   +  - ]
     562   [ +  +  +  -  :       7308 :         snprintf(nvmf_data->subnqn, sizeof(nvmf_data->subnqn), "%s", ctrlr->trid.subnqn);
                   +  - ]
     563                 :            : 
     564                 :       7308 :         rc = nvme_qpair_submit_request(qpair, req);
     565         [ +  + ]:       7308 :         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   [ +  +  +  -  :       7308 :         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                 :          0 :         }
     577                 :            : 
     578   [ +  -  +  -  :       7308 :         qpair->auth.flags = 0;
                   +  - ]
     579   [ +  -  +  - ]:       7308 :         qpair->poll_status = status;
     580                 :       7308 :         return 0;
     581                 :       1684 : }
     582                 :            : 
     583                 :            : int
     584                 :     332881 : nvme_fabric_qpair_connect_poll(struct spdk_nvme_qpair *qpair)
     585                 :            : {
     586                 :            :         struct nvme_completion_poll_status *status;
     587                 :            :         struct spdk_nvmf_fabric_connect_rsp *rsp;
     588                 :            :         struct spdk_nvme_ctrlr *ctrlr;
     589                 :     332881 :         int rc = 0;
     590                 :            : 
     591   [ +  -  +  - ]:     332881 :         ctrlr = qpair->ctrlr;
     592   [ +  -  +  - ]:     332881 :         status = qpair->poll_status;
     593                 :            : 
     594         [ +  + ]:     332881 :         if (nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL) == -EAGAIN) {
     595                 :     325573 :                 return -EAGAIN;
     596                 :            :         }
     597                 :            : 
     598   [ +  +  +  +  :       7308 :         if (status->timed_out || spdk_nvme_cpl_is_error(&status->cpl)) {
          +  +  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     599   [ +  +  +  +  :        860 :                 SPDK_ERRLOG("Connect command failed, rc %d, trtype:%s adrfam:%s "
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     600                 :            :                             "traddr:%s trsvcid:%s subnqn:%s\n",
     601                 :            :                             status->timed_out ? -ECANCELED : -EIO,
     602                 :            :                             spdk_nvme_transport_id_trtype_str(ctrlr->trid.trtype),
     603                 :            :                             spdk_nvme_transport_id_adrfam_str(ctrlr->trid.adrfam),
     604                 :            :                             ctrlr->trid.traddr,
     605                 :            :                             ctrlr->trid.trsvcid,
     606                 :            :                             ctrlr->trid.subnqn);
     607   [ +  +  +  +  :        860 :                 if (status->timed_out) {
             #  #  #  # ]
     608                 :          4 :                         rc = -ECANCELED;
     609                 :          1 :                 } else {
     610   [ #  #  #  #  :        856 :                         SPDK_ERRLOG("Connect command completed with error: sct %d, sc %d\n",
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     611                 :            :                                     status->cpl.status.sct, status->cpl.status.sc);
     612                 :        856 :                         rc = -EIO;
     613                 :            :                 }
     614                 :            : 
     615                 :        860 :                 goto finish;
     616                 :            :         }
     617                 :            : 
     618         [ +  - ]:       6448 :         rsp = (struct spdk_nvmf_fabric_connect_rsp *)&status->cpl;
     619         [ +  + ]:       6448 :         if (nvme_qpair_is_admin_queue(qpair)) {
     620   [ +  -  +  -  :       2528 :                 ctrlr->cntlid = rsp->status_code_specific.success.cntlid;
          +  -  +  -  +  
                -  +  - ]
     621   [ +  +  +  +  :       2528 :                 SPDK_DEBUGLOG(nvme, "CNTLID 0x%04" PRIx16 "\n", ctrlr->cntlid);
          +  -  #  #  #  
                      # ]
     622                 :        841 :         }
     623   [ +  +  +  -  :       6448 :         if (rsp->status_code_specific.success.authreq.atr) {
          +  -  +  -  +  
                      - ]
     624   [ #  #  #  #  :       1008 :                 qpair->auth.flags |= NVME_QPAIR_AUTH_FLAG_ATR;
          #  #  #  #  #  
                      # ]
     625                 :          0 :         }
     626   [ +  -  +  -  :       6448 :         if (rsp->status_code_specific.success.authreq.ascr) {
          +  -  +  -  +  
                      - ]
     627   [ #  #  #  #  :          0 :                 qpair->auth.flags |= NVME_QPAIR_AUTH_FLAG_ASCR;
          #  #  #  #  #  
                      # ]
     628                 :          0 :         }
     629                 :       4766 : finish:
     630   [ +  -  +  - ]:       7308 :         qpair->poll_status = NULL;
     631   [ +  +  +  +  :       7308 :         if (!status->timed_out) {
             +  -  -  + ]
     632   [ +  -  +  - ]:       7304 :                 spdk_free(status->dma_data);
     633                 :       7304 :                 free(status);
     634                 :       1682 :         }
     635                 :            : 
     636                 :       7308 :         return rc;
     637                 :      16808 : }
     638                 :            : 
     639                 :            : bool
     640                 :       6440 : nvme_fabric_qpair_auth_required(struct spdk_nvme_qpair *qpair)
     641                 :            : {
     642   [ +  -  +  - ]:       6440 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     643                 :            : 
     644   [ +  -  +  -  :       8120 :         return qpair->auth.flags & (NVME_QPAIR_AUTH_FLAG_ATR | NVME_QPAIR_AUTH_FLAG_ASCR) ||
          +  -  -  +  +  
          -  -  +  +  -  
                   +  - ]
     645   [ +  +  +  +  :       6440 :                ctrlr->opts.dhchap_ctrlr_key != NULL || qpair->auth.cb_fn != NULL;
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     646                 :            : }
     647                 :            : 
     648                 :            : int
     649                 :         16 : nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries)
     650                 :            : {
     651                 :            :         int rc;
     652                 :            : 
     653                 :         16 :         rc = nvme_fabric_qpair_connect_async(qpair, num_entries);
     654         [ +  + ]:         16 :         if (rc) {
     655                 :          4 :                 return rc;
     656                 :            :         }
     657                 :            : 
     658                 :          3 :         do {
     659                 :            :                 /* Wait until the command completes or times out */
     660                 :         12 :                 rc = nvme_fabric_qpair_connect_poll(qpair);
     661         [ +  + ]:         12 :         } while (rc == -EAGAIN);
     662                 :            : 
     663                 :         12 :         return rc;
     664                 :          4 : }

Generated by: LCOV version 1.15