LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_poll_group.c (source / functions) Hit Total Coverage
Test: Combined Lines: 199 269 74.0 %
Date: 2024-12-15 12:38:17 Functions: 18 22 81.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 312 922 33.8 %

           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                 :            : struct spdk_nvme_poll_group *
      11                 :       2451 : spdk_nvme_poll_group_create(void *ctx, struct spdk_nvme_accel_fn_table *table)
      12                 :            : {
      13                 :            :         struct spdk_nvme_poll_group *group;
      14                 :            :         int rc;
      15                 :            : 
      16                 :       2451 :         group = calloc(1, sizeof(*group));
      17         [ +  + ]:       2451 :         if (group == NULL) {
      18                 :          3 :                 return NULL;
      19                 :            :         }
      20                 :            : 
      21   [ +  -  +  -  :       2448 :         group->accel_fn_table.table_size = sizeof(struct spdk_nvme_accel_fn_table);
                   +  - ]
      22   [ +  +  +  -  :       2448 :         if (table && table->table_size != 0) {
             +  -  +  - ]
      23   [ +  -  +  -  :       2172 :                 group->accel_fn_table.table_size = table->table_size;
          +  -  +  -  +  
                      - ]
      24                 :            : #define SET_FIELD(field) \
      25                 :            :         if (offsetof(struct spdk_nvme_accel_fn_table, field) + sizeof(table->field) <= table->table_size) { \
      26                 :            :                 group->accel_fn_table.field = table->field; \
      27                 :            :         } \
      28                 :            : 
      29   [ +  -  +  -  :       2172 :                 SET_FIELD(append_crc32c);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      30   [ +  -  +  -  :       2172 :                 SET_FIELD(append_copy);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      31   [ +  -  +  -  :       2172 :                 SET_FIELD(finish_sequence);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      32   [ +  -  +  -  :       2172 :                 SET_FIELD(reverse_sequence);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      33   [ +  -  +  -  :       2172 :                 SET_FIELD(abort_sequence);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
      34                 :            :                 /* Do not remove this statement, you should always update this statement when you adding a new field,
      35                 :            :                  * and do not forget to add the SET_FIELD statement for your added field. */
      36                 :            :                 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_accel_fn_table) == 56, "Incorrect size");
      37                 :            : 
      38                 :            : #undef SET_FIELD
      39                 :          1 :         }
      40                 :            : 
      41                 :            :         /* Make sure either all or none of the sequence manipulation callbacks are implemented */
      42   [ +  +  +  -  :       4621 :         if ((group->accel_fn_table.finish_sequence && group->accel_fn_table.reverse_sequence &&
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  -  + ]
      43   [ +  -  +  +  :       4620 :              group->accel_fn_table.abort_sequence) !=
                   +  - ]
      44   [ +  +  +  -  :       2724 :             (group->accel_fn_table.finish_sequence || group->accel_fn_table.reverse_sequence ||
          +  -  -  +  #  
          #  #  #  #  #  
                   #  # ]
      45   [ -  +  #  #  :        276 :              group->accel_fn_table.abort_sequence)) {
                   #  # ]
      46                 :          0 :                 SPDK_ERRLOG("Invalid accel_fn_table configuration: either all or none of the "
      47                 :            :                             "sequence callbacks must be provided\n");
      48                 :          0 :                 free(group);
      49                 :          0 :                 return NULL;
      50                 :            :         }
      51                 :            : 
      52                 :            :         /* Make sure that sequence callbacks are implemented if append* callbacks are provided */
      53   [ +  +  +  +  :       2449 :         if ((group->accel_fn_table.append_crc32c || group->accel_fn_table.append_copy) &&
          +  -  -  +  #  
          #  #  #  #  #  
                   +  - ]
      54   [ +  +  +  -  :       2172 :             !group->accel_fn_table.finish_sequence) {
                   +  - ]
      55                 :          0 :                 SPDK_ERRLOG("Invalid accel_fn_table configuration: append_crc32c and/or append_copy require sequence "
      56                 :            :                             "callbacks to be provided\n");
      57                 :          0 :                 free(group);
      58                 :          0 :                 return NULL;
      59                 :            :         }
      60                 :            : 
      61                 :            :         /* If interrupt is enabled, this fd_group will be used to manage events triggerd on file
      62                 :            :          * descriptors of all the qpairs in this poll group */
      63         [ +  - ]:       2448 :         rc = spdk_fd_group_create(&group->fgrp);
      64         [ -  + ]:       2448 :         if (rc) {
      65                 :            :                 /* Ignore this for non-Linux platforms, as fd_groups aren't supported there. */
      66                 :            : #if defined(__linux__)
      67                 :          0 :                 SPDK_ERRLOG("Cannot create fd group for the nvme poll group\n");
      68                 :          0 :                 free(group);
      69                 :          0 :                 return NULL;
      70                 :            : #endif
      71                 :            :         }
      72                 :            : 
      73   [ -  +  -  + ]:       2448 :         group->disconnect_qpair_fd = -1;
      74   [ -  +  -  + ]:       2448 :         group->ctx = ctx;
      75   [ -  +  -  +  :       2448 :         STAILQ_INIT(&group->tgroups);
          -  +  -  +  -  
          +  -  +  -  +  
                   -  + ]
      76                 :            : 
      77                 :       2448 :         return group;
      78                 :          1 : }
      79                 :            : 
      80                 :            : int
      81                 :          0 : spdk_nvme_poll_group_get_fd(struct spdk_nvme_poll_group *group)
      82                 :            : {
      83   [ #  #  #  #  :          0 :         if (!group->fgrp) {
                   #  # ]
      84                 :          0 :                 SPDK_ERRLOG("No fd group present for the nvme poll group.\n");
      85         [ #  # ]:          0 :                 assert(false);
      86                 :            :                 return -EINVAL;
      87                 :            :         }
      88                 :            : 
      89   [ #  #  #  # ]:          0 :         return spdk_fd_group_get_fd(group->fgrp);
      90                 :            : }
      91                 :            : 
      92                 :            : struct spdk_fd_group *
      93                 :          2 : spdk_nvme_poll_group_get_fd_group(struct spdk_nvme_poll_group *group)
      94                 :            : {
      95   [ #  #  #  # ]:          2 :         return group->fgrp;
      96                 :            : }
      97                 :            : 
      98                 :            : int
      99                 :          2 : spdk_nvme_poll_group_set_interrupt_callback(struct spdk_nvme_poll_group *group,
     100                 :            :                 spdk_nvme_poll_group_interrupt_cb cb_fn, void *cb_ctx)
     101                 :            : {
     102   [ -  +  -  -  :          2 :         if (group->interrupt.cb_fn != NULL && cb_fn != NULL) {
          #  #  #  #  #  
                      # ]
     103                 :          0 :                 return -EEXIST;
     104                 :            :         }
     105                 :            : 
     106   [ #  #  #  #  :          2 :         group->interrupt.cb_fn = cb_fn;
                   #  # ]
     107   [ #  #  #  #  :          2 :         group->interrupt.cb_ctx = cb_ctx;
                   #  # ]
     108                 :            : 
     109                 :          2 :         return 0;
     110                 :          0 : }
     111                 :            : 
     112                 :            : struct spdk_nvme_poll_group *
     113                 :          0 : spdk_nvme_qpair_get_optimal_poll_group(struct spdk_nvme_qpair *qpair)
     114                 :            : {
     115                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     116                 :            : 
     117   [ #  #  #  # ]:          0 :         tgroup = nvme_transport_qpair_get_optimal_poll_group(qpair->transport, qpair);
     118                 :            : 
     119         [ #  # ]:          0 :         if (tgroup == NULL) {
     120                 :          0 :                 return NULL;
     121                 :            :         }
     122                 :            : 
     123   [ #  #  #  # ]:          0 :         return tgroup->group;
     124                 :          0 : }
     125                 :            : 
     126                 :            : #ifdef __linux__
     127                 :            : static int
     128                 :          2 : nvme_poll_group_read_disconnect_qpair_fd(void *arg)
     129                 :            : {
     130                 :          2 :         struct spdk_nvme_poll_group *group = arg;
     131                 :            : 
     132   [ +  -  #  #  :          2 :         if (group->interrupt.cb_fn != NULL) {
             #  #  #  # ]
     133   [ #  #  #  #  :          2 :                 group->interrupt.cb_fn(group, group->interrupt.cb_ctx);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     134                 :          0 :         }
     135                 :            : 
     136                 :          2 :         return 0;
     137                 :            : }
     138                 :            : 
     139                 :            : void
     140                 :       2600 : nvme_poll_group_write_disconnect_qpair_fd(struct spdk_nvme_poll_group *group)
     141                 :            : {
     142                 :       2600 :         uint64_t notify = 1;
     143                 :            :         int rc;
     144                 :            : 
     145   [ +  +  +  +  :       2600 :         if (!group->enable_interrupts) {
             +  -  -  + ]
     146                 :       2598 :                 return;
     147                 :            :         }
     148                 :            : 
     149                 :            :         /* Write to the disconnect qpair fd. This will generate event on the epoll fd of poll
     150                 :            :          * group. We then check for disconnected qpairs either in spdk_nvme_poll_group_wait() or
     151                 :            :          * in transport's poll_group_process_completions() callback.
     152                 :            :          */
     153   [ #  #  #  # ]:          2 :         rc = write(group->disconnect_qpair_fd, &notify, sizeof(notify));
     154         [ -  + ]:          2 :         if (rc < 0) {
     155         [ #  # ]:          0 :                 SPDK_ERRLOG("failed to write the disconnect qpair fd: %s.\n", strerror(errno));
     156                 :          0 :         }
     157                 :          1 : }
     158                 :            : 
     159                 :            : static int
     160                 :          2 : nvme_poll_group_add_disconnect_qpair_fd(struct spdk_nvme_poll_group *group)
     161                 :            : {
     162                 :          2 :         struct spdk_event_handler_opts opts = {};
     163                 :            :         int fd;
     164                 :            : 
     165                 :          2 :         fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
     166         [ -  + ]:          2 :         if (fd < 0) {
     167                 :          0 :                 return fd;
     168                 :            :         }
     169                 :            : 
     170   [ -  +  #  #  :          2 :         assert(group->disconnect_qpair_fd == -1);
             #  #  #  # ]
     171   [ #  #  #  # ]:          2 :         group->disconnect_qpair_fd = fd;
     172                 :            : 
     173                 :          2 :         spdk_fd_group_get_default_event_handler_opts(&opts, sizeof(opts));
     174         [ #  # ]:          2 :         opts.fd_type = SPDK_FD_TYPE_EVENTFD;
     175                 :            : 
     176   [ #  #  #  # ]:          2 :         return SPDK_FD_GROUP_ADD_EXT(group->fgrp, fd, nvme_poll_group_read_disconnect_qpair_fd,
     177                 :            :                                      group, &opts);
     178                 :          0 : }
     179                 :            : 
     180                 :            : #else
     181                 :            : 
     182                 :            : void
     183                 :            : nvme_poll_group_write_disconnect_qpair_fd(struct spdk_nvme_poll_group *group)
     184                 :            : {
     185                 :            : }
     186                 :            : 
     187                 :            : static int
     188                 :            : nvme_poll_group_add_disconnect_qpair_fd(struct spdk_nvme_poll_group *group)
     189                 :            : {
     190                 :            :         return -ENOTSUP;
     191                 :            : }
     192                 :            : 
     193                 :            : #endif
     194                 :            : 
     195                 :            : int
     196                 :       2758 : spdk_nvme_poll_group_add(struct spdk_nvme_poll_group *group, struct spdk_nvme_qpair *qpair)
     197                 :            : {
     198                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     199                 :            :         const struct spdk_nvme_transport *transport;
     200                 :            :         int rc;
     201                 :            : 
     202         [ +  + ]:       2758 :         if (nvme_qpair_get_state(qpair) != NVME_QPAIR_DISCONNECTED) {
     203                 :          3 :                 return -EINVAL;
     204                 :            :         }
     205                 :            : 
     206   [ +  +  +  +  :       2755 :         if (!group->enable_interrupts_is_valid) {
             +  -  -  + ]
     207   [ +  -  +  - ]:       2436 :                 group->enable_interrupts_is_valid = true;
     208   [ +  +  +  -  :       2436 :                 group->enable_interrupts = qpair->ctrlr->opts.enable_interrupts;
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     209   [ +  +  +  +  :       2436 :                 if (group->enable_interrupts) {
             +  -  +  - ]
     210                 :          2 :                         rc = nvme_poll_group_add_disconnect_qpair_fd(group);
     211         [ -  + ]:          2 :                         if (rc != 0) {
     212                 :          0 :                                 return rc;
     213                 :            :                         }
     214                 :          0 :                 }
     215   [ +  +  -  +  :        320 :         } else if (qpair->ctrlr->opts.enable_interrupts != group->enable_interrupts) {
          +  +  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     216   [ +  +  +  -  :          3 :                 SPDK_ERRLOG("Queue pair %s interrupts cannot be added to poll group\n",
          #  #  #  #  #  
                #  #  # ]
     217                 :            :                             qpair->ctrlr->opts.enable_interrupts ? "without" : "with");
     218                 :          3 :                 return -EINVAL;
     219                 :            :         }
     220                 :            : 
     221   [ +  +  +  -  :       2782 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          +  -  +  -  #  
             #  #  #  #  
                      # ]
     222   [ +  +  #  #  :        334 :                 if (tgroup->transport == qpair->transport) {
          #  #  #  #  #  
                      # ]
     223                 :        304 :                         break;
     224                 :            :                 }
     225                 :          0 :         }
     226                 :            : 
     227                 :            :         /* See if a new transport has been added (dlopen style) and we need to update the poll group */
     228         [ +  + ]:       2752 :         if (!tgroup) {
     229                 :       2448 :                 transport = nvme_get_first_transport();
     230         [ +  + ]:       3884 :                 while (transport != NULL) {
     231   [ +  +  +  -  :       3878 :                         if (transport == qpair->transport) {
                   -  + ]
     232                 :       2442 :                                 tgroup = nvme_transport_poll_group_create(transport);
     233         [ +  + ]:       2442 :                                 if (tgroup == NULL) {
     234                 :          0 :                                         return -ENOMEM;
     235                 :            :                                 }
     236   [ -  +  -  + ]:       2442 :                                 tgroup->group = group;
     237   [ -  +  -  +  :       2442 :                                 STAILQ_INSERT_TAIL(&group->tgroups, tgroup, link);
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     238                 :       2442 :                                 break;
     239                 :            :                         }
     240                 :       1436 :                         transport = nvme_get_next_transport(transport);
     241                 :            :                 }
     242                 :          1 :         }
     243                 :            : 
     244         [ +  + ]:       2752 :         return tgroup ? nvme_transport_poll_group_add(tgroup, qpair) : -ENODEV;
     245                 :          1 : }
     246                 :            : 
     247                 :            : int
     248                 :       2746 : spdk_nvme_poll_group_remove(struct spdk_nvme_poll_group *group, struct spdk_nvme_qpair *qpair)
     249                 :            : {
     250                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     251                 :            : 
     252   [ +  +  +  -  :       2770 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          +  -  +  -  #  
             #  #  #  #  
                      # ]
     253   [ +  +  +  -  :       2767 :                 if (tgroup->transport == qpair->transport) {
          +  -  +  -  -  
                      + ]
     254                 :       2743 :                         return nvme_transport_poll_group_remove(tgroup, qpair);
     255                 :            :                 }
     256                 :          0 :         }
     257                 :            : 
     258                 :          3 :         return -ENODEV;
     259                 :          1 : }
     260                 :            : 
     261                 :            : static int
     262                 :     158074 : nvme_qpair_process_completion_wrapper(void *arg)
     263                 :            : {
     264                 :     158074 :         struct spdk_nvme_qpair *qpair = arg;
     265                 :            : 
     266                 :     158074 :         return spdk_nvme_qpair_process_completions(qpair, 0);
     267                 :            : }
     268                 :            : 
     269                 :            : static int
     270                 :       3786 : nvme_poll_group_add_qpair_fd(struct spdk_nvme_qpair *qpair)
     271                 :            : {
     272                 :            :         struct spdk_nvme_poll_group *group;
     273                 :       3786 :         struct spdk_event_handler_opts opts = {
     274                 :            :                 .opts_size = SPDK_SIZEOF(&opts, fd_type),
     275                 :            :         };
     276                 :            :         int fd;
     277                 :            : 
     278   [ +  -  +  -  :       3786 :         group = qpair->poll_group->group;
             +  -  +  - ]
     279   [ +  +  +  +  :       3786 :         if (group->enable_interrupts == false) {
             +  -  -  + ]
     280                 :       3784 :                 return 0;
     281                 :            :         }
     282                 :            : 
     283                 :          2 :         fd = spdk_nvme_qpair_get_fd(qpair, &opts);
     284         [ -  + ]:          2 :         if (fd < 0) {
     285                 :          0 :                 SPDK_ERRLOG("Cannot get fd for the qpair: %d\n", fd);
     286                 :          0 :                 return -EINVAL;
     287                 :            :         }
     288                 :            : 
     289   [ #  #  #  # ]:          2 :         return SPDK_FD_GROUP_ADD_EXT(group->fgrp, fd, nvme_qpair_process_completion_wrapper,
     290                 :            :                                      qpair, &opts);
     291                 :          1 : }
     292                 :            : 
     293                 :            : static void
     294                 :       2719 : nvme_poll_group_remove_qpair_fd(struct spdk_nvme_qpair *qpair)
     295                 :            : {
     296                 :            :         struct spdk_nvme_poll_group *group;
     297                 :            :         int fd;
     298                 :            : 
     299   [ +  -  +  -  :       2719 :         group = qpair->poll_group->group;
             +  -  +  - ]
     300   [ +  +  +  +  :       2719 :         if (group->enable_interrupts == false) {
             +  -  -  + ]
     301                 :       2717 :                 return;
     302                 :            :         }
     303                 :            : 
     304                 :          2 :         fd = spdk_nvme_qpair_get_fd(qpair, NULL);
     305         [ -  + ]:          2 :         if (fd < 0) {
     306                 :          0 :                 SPDK_ERRLOG("Cannot get fd for the qpair: %d\n", fd);
     307         [ #  # ]:          0 :                 assert(false);
     308                 :            :                 return;
     309                 :            :         }
     310                 :            : 
     311   [ #  #  #  # ]:          2 :         spdk_fd_group_remove(group->fgrp, fd);
     312                 :          1 : }
     313                 :            : 
     314                 :            : int
     315                 :       3786 : nvme_poll_group_connect_qpair(struct spdk_nvme_qpair *qpair)
     316                 :            : {
     317                 :            :         int rc;
     318                 :            : 
     319                 :       3786 :         rc = nvme_transport_poll_group_connect_qpair(qpair);
     320         [ -  + ]:       3786 :         if (rc != 0) {
     321                 :          0 :                 return rc;
     322                 :            :         }
     323                 :            : 
     324                 :       3786 :         rc = nvme_poll_group_add_qpair_fd(qpair);
     325         [ +  + ]:       3786 :         if (rc != 0) {
     326                 :          0 :                 nvme_transport_poll_group_disconnect_qpair(qpair);
     327                 :          0 :                 return rc;
     328                 :            :         }
     329                 :            : 
     330                 :       3786 :         return 0;
     331                 :          1 : }
     332                 :            : 
     333                 :            : int
     334                 :       2719 : nvme_poll_group_disconnect_qpair(struct spdk_nvme_qpair *qpair)
     335                 :            : {
     336                 :       2719 :         nvme_poll_group_remove_qpair_fd(qpair);
     337                 :            : 
     338                 :       2719 :         return nvme_transport_poll_group_disconnect_qpair(qpair);
     339                 :            : }
     340                 :            : 
     341                 :            : int
     342                 :          0 : spdk_nvme_poll_group_wait(struct spdk_nvme_poll_group *group,
     343                 :            :                           spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
     344                 :            : {
     345                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     346                 :          0 :         int num_events, timeout = -1;
     347                 :            : 
     348         [ #  # ]:          0 :         if (disconnected_qpair_cb == NULL) {
     349                 :          0 :                 return -EINVAL;
     350                 :            :         }
     351                 :            : 
     352   [ #  #  #  #  :          0 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     353                 :          0 :                 nvme_transport_poll_group_check_disconnected_qpairs(tgroup, disconnected_qpair_cb);
     354                 :          0 :         }
     355                 :            : 
     356   [ #  #  #  # ]:          0 :         num_events = spdk_fd_group_wait(group->fgrp, timeout);
     357                 :            : 
     358                 :          0 :         return num_events;
     359                 :          0 : }
     360                 :            : 
     361                 :            : int64_t
     362                 : 1556023784 : spdk_nvme_poll_group_process_completions(struct spdk_nvme_poll_group *group,
     363                 :            :                 uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
     364                 :            : {
     365                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     366                 : 1556023784 :         int64_t local_completions = 0, error_reason = 0, num_completions = 0;
     367                 :            : 
     368         [ +  + ]: 1556023784 :         if (disconnected_qpair_cb == NULL) {
     369                 :          0 :                 return -EINVAL;
     370                 :            :         }
     371                 :            : 
     372   [ +  +  +  +  : 1556023784 :         if (spdk_unlikely(group->in_process_completions)) {
             +  -  -  + ]
     373                 :    1306307 :                 return 0;
     374                 :            :         }
     375   [ +  -  +  - ]: 1554717477 :         group->in_process_completions = true;
     376                 :            : 
     377   [ +  +  +  -  : 3109434951 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          +  -  +  +  +  
             -  +  -  +  
                      - ]
     378                 : 1554717568 :                 local_completions = nvme_transport_poll_group_process_completions(tgroup, completions_per_qpair,
     379                 :         94 :                                     disconnected_qpair_cb);
     380   [ +  +  +  - ]: 1554717474 :                 if (local_completions < 0 && error_reason == 0) {
     381                 :         40 :                         error_reason = local_completions;
     382                 :          0 :                 } else {
     383         [ +  - ]: 1554717434 :                         num_completions += local_completions;
     384                 :            :                         /* Just to be safe */
     385   [ +  +  #  # ]: 1554717434 :                         assert(num_completions >= 0);
     386                 :            :                 }
     387                 :         94 :         }
     388   [ +  -  +  - ]: 1554717477 :         group->in_process_completions = false;
     389                 :            : 
     390         [ +  + ]: 1554717477 :         return error_reason ? error_reason : num_completions;
     391                 :         94 : }
     392                 :            : 
     393                 :            : int
     394                 :     543837 : spdk_nvme_poll_group_all_connected(struct spdk_nvme_poll_group *group)
     395                 :            : {
     396                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     397                 :            :         struct spdk_nvme_qpair *qpair;
     398                 :     543837 :         int rc = 0;
     399                 :            : 
     400   [ +  +  #  #  :    1087674 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     401   [ -  +  #  #  :     543837 :                 if (!STAILQ_EMPTY(&tgroup->disconnected_qpairs)) {
             #  #  #  # ]
     402                 :            :                         /* Treat disconnected qpairs as highest priority for notification.
     403                 :            :                          * This means we can just return immediately here.
     404                 :            :                          */
     405                 :          0 :                         return -EIO;
     406                 :            :                 }
     407   [ +  +  #  #  :     546253 :                 STAILQ_FOREACH(qpair, &tgroup->connected_qpairs, poll_group_stailq) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     408         [ -  + ]:     546001 :                         if (nvme_qpair_get_state(qpair) < NVME_QPAIR_CONNECTING) {
     409                 :          0 :                                 return -EIO;
     410         [ +  + ]:     546001 :                         } else if (nvme_qpair_get_state(qpair) == NVME_QPAIR_CONNECTING) {
     411                 :     543585 :                                 rc = -EAGAIN;
     412                 :            :                                 /* Break so that we can check the remaining transport groups,
     413                 :            :                                  * in case any of them have a disconnected qpair.
     414                 :            :                                  */
     415                 :     543585 :                                 break;
     416                 :            :                         }
     417                 :          0 :                 }
     418                 :          0 :         }
     419                 :            : 
     420                 :     543837 :         return rc;
     421                 :          0 : }
     422                 :            : 
     423                 :            : void *
     424                 :          0 : spdk_nvme_poll_group_get_ctx(struct spdk_nvme_poll_group *group)
     425                 :            : {
     426   [ #  #  #  # ]:          0 :         return group->ctx;
     427                 :            : }
     428                 :            : 
     429                 :            : int
     430                 :       2451 : spdk_nvme_poll_group_destroy(struct spdk_nvme_poll_group *group)
     431                 :            : {
     432                 :            :         struct spdk_nvme_transport_poll_group *tgroup, *tmp_tgroup;
     433   [ +  -  +  - ]:       2451 :         struct spdk_fd_group *fgrp = group->fgrp;
     434                 :            : 
     435   [ +  +  +  -  :       4878 :         STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
     436   [ +  -  +  -  :       2430 :                 STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     437         [ +  + ]:       2430 :                 if (nvme_transport_poll_group_destroy(tgroup) != 0) {
     438   [ #  #  #  #  :          3 :                         STAILQ_INSERT_TAIL(&group->tgroups, tgroup, link);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     439                 :          3 :                         return -EBUSY;
     440                 :            :                 }
     441                 :            : 
     442                 :          1 :         }
     443                 :            : 
     444         [ +  - ]:       2448 :         if (fgrp) {
     445   [ +  +  +  +  :       2448 :                 if (group->enable_interrupts) {
             +  -  +  - ]
     446   [ #  #  #  # ]:          2 :                         spdk_fd_group_remove(fgrp, group->disconnect_qpair_fd);
     447   [ #  #  #  # ]:          2 :                         close(group->disconnect_qpair_fd);
     448                 :          0 :                 }
     449                 :       2448 :                 spdk_fd_group_destroy(fgrp);
     450                 :          1 :         }
     451                 :            : 
     452                 :       2448 :         free(group);
     453                 :            : 
     454                 :       2448 :         return 0;
     455                 :          1 : }
     456                 :            : 
     457                 :            : int
     458                 :         14 : spdk_nvme_poll_group_get_stats(struct spdk_nvme_poll_group *group,
     459                 :            :                                struct spdk_nvme_poll_group_stat **stats)
     460                 :            : {
     461                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     462                 :            :         struct spdk_nvme_poll_group_stat *result;
     463                 :         14 :         uint32_t transports_count = 0;
     464                 :            :         /* Not all transports used by this poll group may support statistics reporting */
     465                 :         14 :         uint32_t reported_stats_count = 0;
     466                 :            :         int rc;
     467                 :            : 
     468   [ -  +  #  # ]:         14 :         assert(group);
     469   [ -  +  #  # ]:         14 :         assert(stats);
     470                 :            : 
     471                 :         14 :         result = calloc(1, sizeof(*result));
     472         [ -  + ]:         14 :         if (!result) {
     473                 :          0 :                 SPDK_ERRLOG("Failed to allocate memory for poll group statistics\n");
     474                 :          0 :                 return -ENOMEM;
     475                 :            :         }
     476                 :            : 
     477   [ +  +  #  #  :         31 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     478                 :         17 :                 transports_count++;
     479                 :          0 :         }
     480                 :            : 
     481   [ #  #  #  # ]:         14 :         result->transport_stat = calloc(transports_count, sizeof(*result->transport_stat));
     482   [ -  +  #  #  :         14 :         if (!result->transport_stat) {
                   #  # ]
     483                 :          0 :                 SPDK_ERRLOG("Failed to allocate memory for poll group statistics\n");
     484                 :          0 :                 free(result);
     485                 :          0 :                 return -ENOMEM;
     486                 :            :         }
     487                 :            : 
     488   [ +  +  #  #  :         31 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     489   [ #  #  #  #  :         17 :                 rc = nvme_transport_poll_group_get_stats(tgroup, &result->transport_stat[reported_stats_count]);
                   #  # ]
     490         [ +  - ]:         17 :                 if (rc == 0) {
     491                 :         17 :                         reported_stats_count++;
     492                 :          0 :                 }
     493                 :          0 :         }
     494                 :            : 
     495         [ +  + ]:         14 :         if (reported_stats_count == 0) {
     496   [ #  #  #  # ]:          3 :                 free(result->transport_stat);
     497                 :          3 :                 free(result);
     498   [ -  +  -  +  :          3 :                 SPDK_DEBUGLOG(nvme, "No transport statistics available\n");
                   #  # ]
     499                 :          3 :                 return -ENOTSUP;
     500                 :            :         }
     501                 :            : 
     502   [ #  #  #  # ]:         11 :         result->num_transports = reported_stats_count;
     503         [ #  # ]:         11 :         *stats = result;
     504                 :            : 
     505                 :         11 :         return 0;
     506                 :          0 : }
     507                 :            : 
     508                 :            : void
     509                 :         11 : spdk_nvme_poll_group_free_stats(struct spdk_nvme_poll_group *group,
     510                 :            :                                 struct spdk_nvme_poll_group_stat *stat)
     511                 :            : {
     512                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     513                 :            :         uint32_t i;
     514                 :         11 :         uint32_t freed_stats __attribute__((unused)) = 0;
     515                 :            : 
     516   [ -  +  #  # ]:         11 :         assert(group);
     517   [ -  +  #  # ]:         11 :         assert(stat);
     518                 :            : 
     519   [ +  +  #  #  :         28 :         for (i = 0; i < stat->num_transports; i++) {
                   #  # ]
     520   [ +  -  #  #  :         17 :                 STAILQ_FOREACH(tgroup, &group->tgroups, link) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     521   [ +  -  #  #  :         17 :                         if (nvme_transport_get_trtype(tgroup->transport) == stat->transport_stat[i]->trtype) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     522   [ #  #  #  #  :         17 :                                 nvme_transport_poll_group_free_stats(tgroup, stat->transport_stat[i]);
             #  #  #  # ]
     523                 :         17 :                                 freed_stats++;
     524                 :         17 :                                 break;
     525                 :            :                         }
     526                 :          0 :                 }
     527                 :          0 :         }
     528                 :            : 
     529   [ -  +  #  #  :         11 :         assert(freed_stats == stat->num_transports);
             #  #  #  # ]
     530                 :            : 
     531   [ #  #  #  # ]:         11 :         free(stat->transport_stat);
     532                 :         11 :         free(stat);
     533                 :         11 : }

Generated by: LCOV version 1.14