LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_poll_group.c (source / functions) Hit Total Coverage
Test: Combined Lines: 129 166 77.7 %
Date: 2024-12-15 15:45:47 Functions: 11 13 84.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 246 682 36.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2020 Intel Corporation.
       3                 :            :  *   Copyright (c) 2021 Mellanox Technologies LTD.
       4                 :            :  *   Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
       5                 :            :  *   All rights reserved.
       6                 :            :  */
       7                 :            : 
       8                 :            : #include "nvme_internal.h"
       9                 :            : 
      10   [ +  +  #  # ]:       2562 : SPDK_LOG_DEPRECATION_REGISTER(nvme_accel_fn_submit_crc,
      11                 :            :                               "spdk_nvme_accel_fn_table.submit_accel_crc32c", "v25.01", 0);
      12                 :            : 
      13                 :            : struct spdk_nvme_poll_group *
      14                 :       2374 : spdk_nvme_poll_group_create(void *ctx, struct spdk_nvme_accel_fn_table *table)
      15                 :            : {
      16                 :            :         struct spdk_nvme_poll_group *group;
      17                 :            : 
      18                 :       2374 :         group = calloc(1, sizeof(*group));
      19         [ +  + ]:       2374 :         if (group == NULL) {
      20                 :          3 :                 return NULL;
      21                 :            :         }
      22                 :            : 
      23   [ +  -  +  -  :       2371 :         group->accel_fn_table.table_size = sizeof(struct spdk_nvme_accel_fn_table);
                   +  - ]
      24   [ +  +  +  -  :       2371 :         if (table && table->table_size != 0) {
             +  -  -  + ]
      25   [ +  -  +  -  :       2098 :                 group->accel_fn_table.table_size = table->table_size;
          +  -  +  -  +  
                      - ]
      26                 :            : #define SET_FIELD(field) \
      27                 :            :         if (offsetof(struct spdk_nvme_accel_fn_table, field) + sizeof(table->field) <= table->table_size) { \
      28                 :            :                 group->accel_fn_table.field = table->field; \
      29                 :            :         } \
      30                 :            : 
      31   [ +  -  +  -  :       2098 :                 SET_FIELD(submit_accel_crc32c);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      32   [ +  -  +  -  :       2098 :                 SET_FIELD(append_crc32c);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      33   [ +  -  +  -  :       2098 :                 SET_FIELD(append_copy);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      34   [ +  -  +  -  :       2098 :                 SET_FIELD(finish_sequence);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      35   [ +  -  +  -  :       2098 :                 SET_FIELD(reverse_sequence);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      36   [ +  -  +  -  :       2098 :                 SET_FIELD(abort_sequence);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      37                 :            :                 /* Do not remove this statement, you should always update this statement when you adding a new field,
      38                 :            :                  * and do not forget to add the SET_FIELD statement for your added field. */
      39                 :            :                 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_accel_fn_table) == 56, "Incorrect size");
      40                 :            : 
      41                 :            : #undef SET_FIELD
      42                 :          1 :         }
      43                 :            : 
      44                 :            :         /* Make sure either all or none of the sequence manipulation callbacks are implemented */
      45   [ +  +  +  -  :       4470 :         if ((group->accel_fn_table.finish_sequence && group->accel_fn_table.reverse_sequence &&
          +  -  +  -  +  
          -  +  -  +  -  
             -  +  -  + ]
      46   [ +  -  +  +  :       4469 :              group->accel_fn_table.abort_sequence) !=
                   +  - ]
      47   [ +  +  +  -  :       2644 :             (group->accel_fn_table.finish_sequence || group->accel_fn_table.reverse_sequence ||
          +  -  -  +  #  
          #  #  #  #  #  
                   #  # ]
      48   [ -  +  #  #  :        273 :              group->accel_fn_table.abort_sequence)) {
                   #  # ]
      49                 :          0 :                 SPDK_ERRLOG("Invalid accel_fn_table configuration: either all or none of the "
      50                 :            :                             "sequence callbacks must be provided\n");
      51                 :          0 :                 free(group);
      52                 :          0 :                 return NULL;
      53                 :            :         }
      54                 :            : 
      55                 :            :         /* Make sure that sequence callbacks are implemented if append* callbacks are provided */
      56   [ +  +  +  +  :       2372 :         if ((group->accel_fn_table.append_crc32c || group->accel_fn_table.append_copy) &&
          +  -  -  +  #  
          #  #  #  #  #  
                   +  - ]
      57   [ +  +  +  -  :       2098 :             !group->accel_fn_table.finish_sequence) {
                   +  - ]
      58                 :          0 :                 SPDK_ERRLOG("Invalid accel_fn_table configuration: append_crc32c and/or append_copy require sequence "
      59                 :            :                             "callbacks to be provided\n");
      60                 :          0 :                 free(group);
      61                 :          0 :                 return NULL;
      62                 :            :         }
      63                 :            : 
      64   [ +  +  +  -  :       2371 :         if (group->accel_fn_table.submit_accel_crc32c != NULL) {
             +  -  +  - ]
      65                 :          0 :                 SPDK_LOG_DEPRECATED(nvme_accel_fn_submit_crc);
      66                 :          0 :         }
      67                 :            : 
      68   [ +  -  +  - ]:       2371 :         group->ctx = ctx;
      69   [ +  -  +  -  :       2371 :         STAILQ_INIT(&group->tgroups);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      70                 :            : 
      71                 :       2371 :         return group;
      72                 :          1 : }
      73                 :            : 
      74                 :            : struct spdk_nvme_poll_group *
      75                 :          0 : spdk_nvme_qpair_get_optimal_poll_group(struct spdk_nvme_qpair *qpair)
      76                 :            : {
      77                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
      78                 :            : 
      79   [ #  #  #  # ]:          0 :         tgroup = nvme_transport_qpair_get_optimal_poll_group(qpair->transport, qpair);
      80                 :            : 
      81         [ #  # ]:          0 :         if (tgroup == NULL) {
      82                 :          0 :                 return NULL;
      83                 :            :         }
      84                 :            : 
      85   [ #  #  #  # ]:          0 :         return tgroup->group;
      86                 :          0 : }
      87                 :            : 
      88                 :            : int
      89                 :       2673 : spdk_nvme_poll_group_add(struct spdk_nvme_poll_group *group, struct spdk_nvme_qpair *qpair)
      90                 :            : {
      91                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
      92                 :            :         const struct spdk_nvme_transport *transport;
      93                 :            : 
      94         [ +  + ]:       2673 :         if (nvme_qpair_get_state(qpair) != NVME_QPAIR_DISCONNECTED) {
      95                 :          3 :                 return -EINVAL;
      96                 :            :         }
      97                 :            : 
      98   [ +  +  +  -  :       2700 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          +  -  +  -  #  
             #  #  #  #  
                      # ]
      99   [ +  +  #  #  :        329 :                 if (tgroup->transport == qpair->transport) {
          #  #  #  #  #  
                      # ]
     100                 :        299 :                         break;
     101                 :            :                 }
     102                 :          0 :         }
     103                 :            : 
     104                 :            :         /* See if a new transport has been added (dlopen style) and we need to update the poll group */
     105         [ +  + ]:       2670 :         if (!tgroup) {
     106                 :       2371 :                 transport = nvme_get_first_transport();
     107         [ +  + ]:       3752 :                 while (transport != NULL) {
     108   [ +  +  +  -  :       3746 :                         if (transport == qpair->transport) {
                   -  + ]
     109                 :       2365 :                                 tgroup = nvme_transport_poll_group_create(transport);
     110         [ +  + ]:       2365 :                                 if (tgroup == NULL) {
     111                 :          0 :                                         return -ENOMEM;
     112                 :            :                                 }
     113   [ +  -  +  - ]:       2365 :                                 tgroup->group = group;
     114   [ +  -  +  -  :       2365 :                                 STAILQ_INSERT_TAIL(&group->tgroups, tgroup, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     115                 :       2365 :                                 break;
     116                 :            :                         }
     117                 :       1381 :                         transport = nvme_get_next_transport(transport);
     118                 :            :                 }
     119                 :          1 :         }
     120                 :            : 
     121         [ +  + ]:       2670 :         return tgroup ? nvme_transport_poll_group_add(tgroup, qpair) : -ENODEV;
     122                 :          1 : }
     123                 :            : 
     124                 :            : int
     125                 :       2664 : spdk_nvme_poll_group_remove(struct spdk_nvme_poll_group *group, struct spdk_nvme_qpair *qpair)
     126                 :            : {
     127                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     128                 :            : 
     129   [ +  +  +  -  :       2688 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          +  -  +  -  #  
             #  #  #  #  
                      # ]
     130   [ +  +  +  -  :       2685 :                 if (tgroup->transport == qpair->transport) {
          +  -  +  -  -  
                      + ]
     131                 :       2661 :                         return nvme_transport_poll_group_remove(tgroup, qpair);
     132                 :            :                 }
     133                 :          0 :         }
     134                 :            : 
     135                 :          3 :         return -ENODEV;
     136                 :          1 : }
     137                 :            : 
     138                 :            : int
     139                 :       3698 : nvme_poll_group_connect_qpair(struct spdk_nvme_qpair *qpair)
     140                 :            : {
     141                 :       3698 :         return nvme_transport_poll_group_connect_qpair(qpair);
     142                 :            : }
     143                 :            : 
     144                 :            : int
     145                 :       2643 : nvme_poll_group_disconnect_qpair(struct spdk_nvme_qpair *qpair)
     146                 :            : {
     147                 :       2643 :         return nvme_transport_poll_group_disconnect_qpair(qpair);
     148                 :            : }
     149                 :            : 
     150                 :            : int64_t
     151                 : 1384915811 : spdk_nvme_poll_group_process_completions(struct spdk_nvme_poll_group *group,
     152                 :            :                 uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
     153                 :            : {
     154                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     155                 : 1384915811 :         int64_t local_completions = 0, error_reason = 0, num_completions = 0;
     156                 :            : 
     157         [ +  + ]: 1384915811 :         if (disconnected_qpair_cb == NULL) {
     158                 :          0 :                 return -EINVAL;
     159                 :            :         }
     160                 :            : 
     161   [ +  +  +  +  : 1384915811 :         if (spdk_unlikely(group->in_process_completions)) {
             +  -  -  + ]
     162                 :    1265650 :                 return 0;
     163                 :            :         }
     164   [ +  -  +  - ]: 1383650161 :         group->in_process_completions = true;
     165                 :            : 
     166   [ +  +  +  -  : 2767300319 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          +  -  +  +  +  
             -  +  -  +  
                      - ]
     167                 : 1383650248 :                 local_completions = nvme_transport_poll_group_process_completions(tgroup, completions_per_qpair,
     168                 :         90 :                                     disconnected_qpair_cb);
     169   [ +  +  +  - ]: 1383650158 :                 if (local_completions < 0 && error_reason == 0) {
     170                 :         33 :                         error_reason = local_completions;
     171                 :          0 :                 } else {
     172         [ +  - ]: 1383650125 :                         num_completions += local_completions;
     173                 :            :                         /* Just to be safe */
     174   [ +  +  #  # ]: 1383650125 :                         assert(num_completions >= 0);
     175                 :            :                 }
     176                 :         90 :         }
     177   [ +  -  +  - ]: 1383650161 :         group->in_process_completions = false;
     178                 :            : 
     179         [ +  + ]: 1383650161 :         return error_reason ? error_reason : num_completions;
     180                 :         90 : }
     181                 :            : 
     182                 :            : int
     183                 :     555204 : spdk_nvme_poll_group_all_connected(struct spdk_nvme_poll_group *group)
     184                 :            : {
     185                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     186                 :            :         struct spdk_nvme_qpair *qpair;
     187                 :     555204 :         int rc = 0;
     188                 :            : 
     189   [ +  +  #  #  :    1110408 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     190   [ -  +  #  #  :     555204 :                 if (!STAILQ_EMPTY(&tgroup->disconnected_qpairs)) {
             #  #  #  # ]
     191                 :            :                         /* Treat disconnected qpairs as highest priority for notification.
     192                 :            :                          * This means we can just return immediately here.
     193                 :            :                          */
     194                 :          0 :                         return -EIO;
     195                 :            :                 }
     196   [ +  +  #  #  :     564706 :                 STAILQ_FOREACH(qpair, &tgroup->connected_qpairs, poll_group_stailq) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     197         [ -  + ]:     564454 :                         if (nvme_qpair_get_state(qpair) < NVME_QPAIR_CONNECTING) {
     198                 :          0 :                                 return -EIO;
     199         [ +  + ]:     564454 :                         } else if (nvme_qpair_get_state(qpair) == NVME_QPAIR_CONNECTING) {
     200                 :     554952 :                                 rc = -EAGAIN;
     201                 :            :                                 /* Break so that we can check the remaining transport groups,
     202                 :            :                                  * in case any of them have a disconnected qpair.
     203                 :            :                                  */
     204                 :     554952 :                                 break;
     205                 :            :                         }
     206                 :          0 :                 }
     207                 :          0 :         }
     208                 :            : 
     209                 :     555204 :         return rc;
     210                 :          0 : }
     211                 :            : 
     212                 :            : void *
     213                 :          0 : spdk_nvme_poll_group_get_ctx(struct spdk_nvme_poll_group *group)
     214                 :            : {
     215   [ #  #  #  # ]:          0 :         return group->ctx;
     216                 :            : }
     217                 :            : 
     218                 :            : int
     219                 :       2374 : spdk_nvme_poll_group_destroy(struct spdk_nvme_poll_group *group)
     220                 :            : {
     221                 :            :         struct spdk_nvme_transport_poll_group *tgroup, *tmp_tgroup;
     222                 :            : 
     223   [ +  +  +  -  :       4727 :         STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
     224   [ +  -  +  -  :       2356 :                 STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     225         [ +  + ]:       2356 :                 if (nvme_transport_poll_group_destroy(tgroup) != 0) {
     226   [ #  #  #  #  :          3 :                         STAILQ_INSERT_TAIL(&group->tgroups, tgroup, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     227                 :          3 :                         return -EBUSY;
     228                 :            :                 }
     229                 :            : 
     230                 :          1 :         }
     231                 :            : 
     232                 :       2371 :         free(group);
     233                 :            : 
     234                 :       2371 :         return 0;
     235                 :          1 : }
     236                 :            : 
     237                 :            : int
     238                 :         14 : spdk_nvme_poll_group_get_stats(struct spdk_nvme_poll_group *group,
     239                 :            :                                struct spdk_nvme_poll_group_stat **stats)
     240                 :            : {
     241                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     242                 :            :         struct spdk_nvme_poll_group_stat *result;
     243                 :         14 :         uint32_t transports_count = 0;
     244                 :            :         /* Not all transports used by this poll group may support statistics reporting */
     245                 :         14 :         uint32_t reported_stats_count = 0;
     246                 :            :         int rc;
     247                 :            : 
     248   [ -  +  #  # ]:         14 :         assert(group);
     249   [ -  +  #  # ]:         14 :         assert(stats);
     250                 :            : 
     251                 :         14 :         result = calloc(1, sizeof(*result));
     252         [ -  + ]:         14 :         if (!result) {
     253                 :          0 :                 SPDK_ERRLOG("Failed to allocate memory for poll group statistics\n");
     254                 :          0 :                 return -ENOMEM;
     255                 :            :         }
     256                 :            : 
     257   [ +  +  #  #  :         31 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     258                 :         17 :                 transports_count++;
     259                 :          0 :         }
     260                 :            : 
     261   [ #  #  #  # ]:         14 :         result->transport_stat = calloc(transports_count, sizeof(*result->transport_stat));
     262   [ -  +  #  #  :         14 :         if (!result->transport_stat) {
                   #  # ]
     263                 :          0 :                 SPDK_ERRLOG("Failed to allocate memory for poll group statistics\n");
     264                 :          0 :                 free(result);
     265                 :          0 :                 return -ENOMEM;
     266                 :            :         }
     267                 :            : 
     268   [ +  +  #  #  :         31 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     269   [ #  #  #  #  :         17 :                 rc = nvme_transport_poll_group_get_stats(tgroup, &result->transport_stat[reported_stats_count]);
                   #  # ]
     270         [ +  - ]:         17 :                 if (rc == 0) {
     271                 :         17 :                         reported_stats_count++;
     272                 :          0 :                 }
     273                 :          0 :         }
     274                 :            : 
     275         [ +  + ]:         14 :         if (reported_stats_count == 0) {
     276   [ #  #  #  # ]:          3 :                 free(result->transport_stat);
     277                 :          3 :                 free(result);
     278   [ -  +  -  +  :          3 :                 SPDK_DEBUGLOG(nvme, "No transport statistics available\n");
                   #  # ]
     279                 :          3 :                 return -ENOTSUP;
     280                 :            :         }
     281                 :            : 
     282   [ #  #  #  # ]:         11 :         result->num_transports = reported_stats_count;
     283         [ #  # ]:         11 :         *stats = result;
     284                 :            : 
     285                 :         11 :         return 0;
     286                 :          0 : }
     287                 :            : 
     288                 :            : void
     289                 :         11 : spdk_nvme_poll_group_free_stats(struct spdk_nvme_poll_group *group,
     290                 :            :                                 struct spdk_nvme_poll_group_stat *stat)
     291                 :            : {
     292                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     293                 :            :         uint32_t i;
     294                 :         11 :         uint32_t freed_stats __attribute__((unused)) = 0;
     295                 :            : 
     296   [ -  +  #  # ]:         11 :         assert(group);
     297   [ -  +  #  # ]:         11 :         assert(stat);
     298                 :            : 
     299   [ +  +  #  #  :         28 :         for (i = 0; i < stat->num_transports; i++) {
                   #  # ]
     300   [ +  -  #  #  :         17 :                 STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     301   [ +  -  #  #  :         17 :                         if (nvme_transport_get_trtype(tgroup->transport) == stat->transport_stat[i]->trtype) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     302   [ #  #  #  #  :         17 :                                 nvme_transport_poll_group_free_stats(tgroup, stat->transport_stat[i]);
             #  #  #  # ]
     303                 :         17 :                                 freed_stats++;
     304                 :         17 :                                 break;
     305                 :            :                         }
     306                 :          0 :                 }
     307                 :          0 :         }
     308                 :            : 
     309   [ -  +  #  #  :         11 :         assert(freed_stats == stat->num_transports);
             #  #  #  # ]
     310                 :            : 
     311   [ #  #  #  # ]:         11 :         free(stat->transport_stat);
     312                 :         11 :         free(stat);
     313                 :         11 : }

Generated by: LCOV version 1.15