LCOV - code coverage report
Current view: top level - spdk/lib/thread - iobuf.c (source / functions) Hit Total Coverage
Test: Combined Lines: 299 370 80.8 %
Date: 2024-12-17 09:18:53 Functions: 18 18 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 678 1986 34.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2023 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/env.h"
       7                 :            : #include "spdk/util.h"
       8                 :            : #include "spdk/likely.h"
       9                 :            : #include "spdk/log.h"
      10                 :            : #include "spdk/thread.h"
      11                 :            : 
      12                 :            : #define IOBUF_MIN_SMALL_POOL_SIZE       64
      13                 :            : #define IOBUF_MIN_LARGE_POOL_SIZE       8
      14                 :            : #define IOBUF_DEFAULT_SMALL_POOL_SIZE   8192
      15                 :            : #define IOBUF_DEFAULT_LARGE_POOL_SIZE   1024
      16                 :            : #define IOBUF_ALIGNMENT                 4096
      17                 :            : #define IOBUF_MIN_SMALL_BUFSIZE         4096
      18                 :            : #define IOBUF_MIN_LARGE_BUFSIZE         8192
      19                 :            : #define IOBUF_DEFAULT_SMALL_BUFSIZE     (8 * 1024)
      20                 :            : /* 132k is a weird choice at first, but this needs to be large enough to accommodate
      21                 :            :  * the default maximum size (128k) plus metadata everywhere. For code paths that
      22                 :            :  * are explicitly configured, the math is instead done properly. This is only
      23                 :            :  * for the default. */
      24                 :            : #define IOBUF_DEFAULT_LARGE_BUFSIZE     (132 * 1024)
      25                 :            : #define IOBUF_MAX_CHANNELS              64
      26                 :            : 
      27                 :            : SPDK_STATIC_ASSERT(sizeof(struct spdk_iobuf_buffer) <= IOBUF_MIN_SMALL_BUFSIZE,
      28                 :            :                    "Invalid data offset");
      29                 :            : 
      30                 :            : static bool g_iobuf_is_initialized = false;
      31                 :            : 
      32                 :            : struct iobuf_channel {
      33                 :            :         spdk_iobuf_entry_stailq_t       small_queue;
      34                 :            :         spdk_iobuf_entry_stailq_t       large_queue;
      35                 :            :         struct spdk_iobuf_channel       *channels[IOBUF_MAX_CHANNELS];
      36                 :            : };
      37                 :            : 
      38                 :            : struct iobuf_module {
      39                 :            :         char                            *name;
      40                 :            :         TAILQ_ENTRY(iobuf_module)       tailq;
      41                 :            : };
      42                 :            : 
      43                 :            : struct iobuf {
      44                 :            :         struct spdk_ring                *small_pool;
      45                 :            :         struct spdk_ring                *large_pool;
      46                 :            :         void                            *small_pool_base;
      47                 :            :         void                            *large_pool_base;
      48                 :            :         struct spdk_iobuf_opts          opts;
      49                 :            :         TAILQ_HEAD(, iobuf_module)      modules;
      50                 :            :         spdk_iobuf_finish_cb            finish_cb;
      51                 :            :         void                            *finish_arg;
      52                 :            : };
      53                 :            : 
      54                 :            : static struct iobuf g_iobuf = {
      55                 :            :         .modules = TAILQ_HEAD_INITIALIZER(g_iobuf.modules),
      56                 :            :         .small_pool = NULL,
      57                 :            :         .large_pool = NULL,
      58                 :            :         .small_pool_base = NULL,
      59                 :            :         .large_pool_base = NULL,
      60                 :            :         .opts = {
      61                 :            :                 .small_pool_count = IOBUF_DEFAULT_SMALL_POOL_SIZE,
      62                 :            :                 .large_pool_count = IOBUF_DEFAULT_LARGE_POOL_SIZE,
      63                 :            :                 .small_bufsize = IOBUF_DEFAULT_SMALL_BUFSIZE,
      64                 :            :                 .large_bufsize = IOBUF_DEFAULT_LARGE_BUFSIZE,
      65                 :            :         },
      66                 :            : };
      67                 :            : 
      68                 :            : struct iobuf_get_stats_ctx {
      69                 :            :         struct spdk_iobuf_module_stats  *modules;
      70                 :            :         uint32_t                        num_modules;
      71                 :            :         spdk_iobuf_get_stats_cb         cb_fn;
      72                 :            :         void                            *cb_arg;
      73                 :            : };
      74                 :            : 
      75                 :            : static int
      76                 :       7169 : iobuf_channel_create_cb(void *io_device, void *ctx)
      77                 :            : {
      78                 :       7169 :         struct iobuf_channel *ch = ctx;
      79                 :            : 
      80   [ +  -  +  -  :       7169 :         STAILQ_INIT(&ch->small_queue);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      81   [ +  -  +  -  :       7169 :         STAILQ_INIT(&ch->large_queue);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      82                 :            : 
      83                 :       7169 :         return 0;
      84                 :            : }
      85                 :            : 
      86                 :            : static void
      87                 :       7169 : iobuf_channel_destroy_cb(void *io_device, void *ctx)
      88                 :            : {
      89                 :       7169 :         struct iobuf_channel *ch __attribute__((unused)) = ctx;
      90                 :            : 
      91   [ +  +  +  -  :       7169 :         assert(STAILQ_EMPTY(&ch->small_queue));
          +  -  +  -  #  
                      # ]
      92   [ +  +  +  -  :       7169 :         assert(STAILQ_EMPTY(&ch->large_queue));
          +  -  +  -  #  
                      # ]
      93                 :       7169 : }
      94                 :            : 
      95                 :            : int
      96                 :       2305 : spdk_iobuf_initialize(void)
      97                 :            : {
      98                 :       2305 :         struct spdk_iobuf_opts *opts = &g_iobuf.opts;
      99                 :       2305 :         int rc = 0;
     100                 :            :         uint64_t i;
     101                 :       1045 :         struct spdk_iobuf_buffer *buf;
     102                 :            : 
     103   [ +  -  +  - ]:       2305 :         g_iobuf.small_pool = spdk_ring_create(SPDK_RING_TYPE_MP_MC, opts->small_pool_count,
     104                 :            :                                               SPDK_ENV_NUMA_ID_ANY);
     105         [ +  + ]:       2305 :         if (!g_iobuf.small_pool) {
     106                 :          0 :                 SPDK_ERRLOG("Failed to create small iobuf pool\n");
     107                 :          0 :                 rc = -ENOMEM;
     108                 :          0 :                 goto error;
     109                 :            :         }
     110                 :            : 
     111                 :            :         /* Round up to the nearest alignment so that each element remains aligned */
     112   [ +  -  +  -  :       2305 :         opts->small_bufsize = SPDK_ALIGN_CEIL(opts->small_bufsize, IOBUF_ALIGNMENT);
             +  -  +  - ]
     113   [ +  -  +  -  :       2305 :         g_iobuf.small_pool_base = spdk_malloc(opts->small_bufsize * opts->small_pool_count, IOBUF_ALIGNMENT,
          +  -  +  -  +  
                      - ]
     114                 :            :                                               NULL, SPDK_ENV_NUMA_ID_ANY, SPDK_MALLOC_DMA);
     115   [ +  +  +  - ]:       2305 :         if (g_iobuf.small_pool_base == NULL) {
     116                 :          0 :                 SPDK_ERRLOG("Unable to allocate requested small iobuf pool size\n");
     117                 :          0 :                 rc = -ENOMEM;
     118                 :          0 :                 goto error;
     119                 :            :         }
     120                 :            : 
     121   [ +  -  +  -  :       2305 :         g_iobuf.large_pool = spdk_ring_create(SPDK_RING_TYPE_MP_MC, opts->large_pool_count,
                   +  - ]
     122                 :            :                                               SPDK_ENV_NUMA_ID_ANY);
     123   [ +  +  +  - ]:       2305 :         if (!g_iobuf.large_pool) {
     124                 :          0 :                 SPDK_ERRLOG("Failed to create large iobuf pool\n");
     125                 :          0 :                 rc = -ENOMEM;
     126                 :          0 :                 goto error;
     127                 :            :         }
     128                 :            : 
     129                 :            :         /* Round up to the nearest alignment so that each element remains aligned */
     130   [ -  +  -  +  :       2305 :         opts->large_bufsize = SPDK_ALIGN_CEIL(opts->large_bufsize, IOBUF_ALIGNMENT);
             -  +  -  + ]
     131   [ -  +  -  +  :       2305 :         g_iobuf.large_pool_base = spdk_malloc(opts->large_bufsize * opts->large_pool_count, IOBUF_ALIGNMENT,
          -  +  -  +  -  
                      + ]
     132                 :            :                                               NULL, SPDK_ENV_NUMA_ID_ANY, SPDK_MALLOC_DMA);
     133   [ -  +  +  - ]:       2305 :         if (g_iobuf.large_pool_base == NULL) {
     134                 :          0 :                 SPDK_ERRLOG("Unable to allocate requested large iobuf pool size\n");
     135                 :          0 :                 rc = -ENOMEM;
     136                 :          0 :                 goto error;
     137                 :            :         }
     138                 :            : 
     139   [ +  +  +  -  :   18983191 :         for (i = 0; i < opts->small_pool_count; i++) {
                   +  + ]
     140   [ +  -  +  -  :   18980886 :                 buf = g_iobuf.small_pool_base + i * opts->small_bufsize;
                   +  - ]
     141                 :   18980886 :                 spdk_ring_enqueue(g_iobuf.small_pool, (void **)&buf, 1, NULL);
     142                 :     475136 :         }
     143                 :            : 
     144   [ +  +  +  -  :    2372537 :         for (i = 0; i < opts->large_pool_count; i++) {
                   +  + ]
     145   [ +  -  +  -  :    2370232 :                 buf = g_iobuf.large_pool_base + i * opts->large_bufsize;
                   +  - ]
     146         [ +  - ]:    2370232 :                 spdk_ring_enqueue(g_iobuf.large_pool, (void **)&buf, 1, NULL);
     147                 :      59392 :         }
     148                 :            : 
     149                 :       2305 :         spdk_io_device_register(&g_iobuf, iobuf_channel_create_cb, iobuf_channel_destroy_cb,
     150                 :            :                                 sizeof(struct iobuf_channel), "iobuf");
     151                 :       2305 :         g_iobuf_is_initialized = true;
     152                 :            : 
     153                 :       2305 :         return 0;
     154                 :          0 : error:
     155         [ #  # ]:          0 :         spdk_free(g_iobuf.small_pool_base);
     156                 :          0 :         spdk_ring_free(g_iobuf.small_pool);
     157         [ #  # ]:          0 :         spdk_free(g_iobuf.large_pool_base);
     158         [ #  # ]:          0 :         spdk_ring_free(g_iobuf.large_pool);
     159                 :            : 
     160                 :          0 :         return rc;
     161                 :         58 : }
     162                 :            : 
     163                 :            : static void
     164                 :       2305 : iobuf_unregister_cb(void *io_device)
     165                 :            : {
     166                 :            :         struct iobuf_module *module;
     167                 :            : 
     168   [ +  +  +  -  :       6648 :         while (!TAILQ_EMPTY(&g_iobuf.modules)) {
                   +  + ]
     169   [ +  -  +  - ]:       4343 :                 module = TAILQ_FIRST(&g_iobuf.modules);
     170   [ +  +  +  -  :       4343 :                 TAILQ_REMOVE(&g_iobuf.modules, module, tailq);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     171   [ +  -  +  - ]:       4343 :                 free(module->name);
     172                 :       4343 :                 free(module);
     173                 :            :         }
     174                 :            : 
     175   [ +  +  +  -  :       2305 :         if (spdk_ring_count(g_iobuf.small_pool) != g_iobuf.opts.small_pool_count) {
                   +  - ]
     176   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("small iobuf pool count is %zu, expected %"PRIu64"\n",
     177                 :            :                             spdk_ring_count(g_iobuf.small_pool), g_iobuf.opts.small_pool_count);
     178                 :          0 :         }
     179                 :            : 
     180   [ +  +  +  -  :       2305 :         if (spdk_ring_count(g_iobuf.large_pool) != g_iobuf.opts.large_pool_count) {
             +  -  +  - ]
     181   [ #  #  #  #  :          0 :                 SPDK_ERRLOG("large iobuf pool count is %zu, expected %"PRIu64"\n",
                   #  # ]
     182                 :            :                             spdk_ring_count(g_iobuf.large_pool), g_iobuf.opts.large_pool_count);
     183                 :          0 :         }
     184                 :            : 
     185         [ +  - ]:       2305 :         spdk_free(g_iobuf.small_pool_base);
     186         [ +  - ]:       2305 :         g_iobuf.small_pool_base = NULL;
     187                 :       2305 :         spdk_ring_free(g_iobuf.small_pool);
     188                 :       2305 :         g_iobuf.small_pool = NULL;
     189                 :            : 
     190         [ +  - ]:       2305 :         spdk_free(g_iobuf.large_pool_base);
     191         [ +  - ]:       2305 :         g_iobuf.large_pool_base = NULL;
     192         [ +  - ]:       2305 :         spdk_ring_free(g_iobuf.large_pool);
     193         [ +  - ]:       2305 :         g_iobuf.large_pool = NULL;
     194                 :            : 
     195   [ +  -  +  - ]:       2305 :         if (g_iobuf.finish_cb != NULL) {
     196   [ +  -  -  +  :       2305 :                 g_iobuf.finish_cb(g_iobuf.finish_arg);
             +  -  +  - ]
     197                 :         58 :         }
     198                 :       2305 : }
     199                 :            : 
     200                 :            : void
     201                 :       2305 : spdk_iobuf_finish(spdk_iobuf_finish_cb cb_fn, void *cb_arg)
     202                 :            : {
     203   [ +  +  +  + ]:       2305 :         if (!g_iobuf_is_initialized) {
     204   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg);
     205                 :          0 :                 return;
     206                 :            :         }
     207                 :            : 
     208                 :       2305 :         g_iobuf_is_initialized = false;
     209         [ +  - ]:       2305 :         g_iobuf.finish_cb = cb_fn;
     210         [ +  - ]:       2305 :         g_iobuf.finish_arg = cb_arg;
     211                 :            : 
     212                 :       2305 :         spdk_io_device_unregister(&g_iobuf, iobuf_unregister_cb);
     213                 :         58 : }
     214                 :            : 
     215                 :            : int
     216                 :        229 : spdk_iobuf_set_opts(const struct spdk_iobuf_opts *opts)
     217                 :            : {
     218         [ +  + ]:        229 :         if (!opts) {
     219                 :          0 :                 SPDK_ERRLOG("opts cannot be NULL\n");
     220                 :          0 :                 return -1;
     221                 :            :         }
     222                 :            : 
     223   [ +  +  +  -  :        229 :         if (!opts->opts_size) {
                   +  - ]
     224                 :          0 :                 SPDK_ERRLOG("opts_size inside opts cannot be zero value\n");
     225                 :          0 :                 return -1;
     226                 :            :         }
     227                 :            : 
     228   [ +  +  +  -  :        229 :         if (opts->small_pool_count < IOBUF_MIN_SMALL_POOL_SIZE) {
                   -  + ]
     229                 :          0 :                 SPDK_ERRLOG("small_pool_count must be at least %" PRIu32 "\n",
     230                 :            :                             IOBUF_MIN_SMALL_POOL_SIZE);
     231                 :          0 :                 return -EINVAL;
     232                 :            :         }
     233   [ +  +  +  -  :        229 :         if (opts->large_pool_count < IOBUF_MIN_LARGE_POOL_SIZE) {
                   -  + ]
     234                 :          0 :                 SPDK_ERRLOG("large_pool_count must be at least %" PRIu32 "\n",
     235                 :            :                             IOBUF_MIN_LARGE_POOL_SIZE);
     236                 :          0 :                 return -EINVAL;
     237                 :            :         }
     238                 :            : 
     239   [ +  +  +  -  :        229 :         if (opts->small_bufsize < IOBUF_MIN_SMALL_BUFSIZE) {
                   -  + ]
     240                 :          0 :                 SPDK_ERRLOG("small_bufsize must be at least %" PRIu32 "\n",
     241                 :            :                             IOBUF_MIN_SMALL_BUFSIZE);
     242                 :          0 :                 return -EINVAL;
     243                 :            :         }
     244                 :            : 
     245   [ +  +  +  -  :        229 :         if (opts->large_bufsize < IOBUF_MIN_LARGE_BUFSIZE) {
                   -  + ]
     246                 :          0 :                 SPDK_ERRLOG("large_bufsize must be at least %" PRIu32 "\n",
     247                 :            :                             IOBUF_MIN_LARGE_BUFSIZE);
     248                 :          0 :                 return -EINVAL;
     249                 :            :         }
     250                 :            : 
     251                 :            : #define SET_FIELD(field) \
     252                 :            :         if (offsetof(struct spdk_iobuf_opts, field) + sizeof(opts->field) <= opts->opts_size) { \
     253                 :            :                 g_iobuf.opts.field = opts->field; \
     254                 :            :         } \
     255                 :            : 
     256   [ +  -  +  -  :        229 :         SET_FIELD(small_pool_count);
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     257   [ +  -  +  -  :        229 :         SET_FIELD(large_pool_count);
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     258   [ +  -  +  -  :        229 :         SET_FIELD(small_bufsize);
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     259   [ +  -  +  -  :        229 :         SET_FIELD(large_bufsize);
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     260                 :            : 
     261   [ +  -  +  -  :        229 :         g_iobuf.opts.opts_size = opts->opts_size;
             +  -  +  - ]
     262                 :            : 
     263                 :            : #undef SET_FIELD
     264                 :            : 
     265                 :        229 :         return 0;
     266                 :          1 : }
     267                 :            : 
     268                 :            : void
     269                 :       8414 : spdk_iobuf_get_opts(struct spdk_iobuf_opts *opts, size_t opts_size)
     270                 :            : {
     271         [ +  + ]:       8414 :         if (!opts) {
     272                 :          0 :                 SPDK_ERRLOG("opts should not be NULL\n");
     273                 :          0 :                 return;
     274                 :            :         }
     275                 :            : 
     276         [ +  + ]:       8414 :         if (!opts_size) {
     277                 :          0 :                 SPDK_ERRLOG("opts_size should not be zero value\n");
     278                 :          0 :                 return;
     279                 :            :         }
     280                 :            : 
     281   [ +  -  +  - ]:       8414 :         opts->opts_size = opts_size;
     282                 :            : 
     283                 :            : #define SET_FIELD(field) \
     284                 :            :         if (offsetof(struct spdk_iobuf_opts, field) + sizeof(opts->field) <= opts_size) { \
     285                 :            :                 opts->field = g_iobuf.opts.field; \
     286                 :            :         } \
     287                 :            : 
     288   [ +  +  +  -  :       8414 :         SET_FIELD(small_pool_count);
          +  -  +  -  +  
                      - ]
     289   [ +  +  +  -  :       8414 :         SET_FIELD(large_pool_count);
          +  -  +  -  +  
                      - ]
     290   [ +  +  +  -  :       8414 :         SET_FIELD(small_bufsize);
          +  -  +  -  +  
                      - ]
     291   [ +  +  +  -  :       8414 :         SET_FIELD(large_bufsize);
          +  -  +  -  +  
                      - ]
     292                 :            : 
     293                 :            : #undef SET_FIELD
     294                 :            : 
     295                 :            :         /* Do not remove this statement, you should always update this statement when you adding a new field,
     296                 :            :          * and do not forget to add the SET_FIELD statement for your added field. */
     297                 :            :         SPDK_STATIC_ASSERT(sizeof(struct spdk_iobuf_opts) == 32, "Incorrect size");
     298                 :        123 : }
     299                 :            : 
     300                 :            : 
     301                 :            : int
     302                 :      22531 : spdk_iobuf_channel_init(struct spdk_iobuf_channel *ch, const char *name,
     303                 :            :                         uint32_t small_cache_size, uint32_t large_cache_size)
     304                 :            : {
     305                 :            :         struct spdk_io_channel *ioch;
     306                 :            :         struct iobuf_channel *iobuf_ch;
     307                 :            :         struct iobuf_module *module;
     308                 :       5950 :         struct spdk_iobuf_buffer *buf;
     309                 :            :         uint32_t i;
     310                 :            : 
     311   [ +  -  +  -  :      36682 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          -  +  +  -  +  
                -  +  - ]
     312   [ +  +  +  +  :      36682 :                 if (strcmp(name, module->name) == 0) {
          +  +  +  -  +  
                      + ]
     313                 :      22531 :                         break;
     314                 :            :                 }
     315                 :        150 :         }
     316                 :            : 
     317         [ +  + ]:      22531 :         if (module == NULL) {
     318                 :          0 :                 SPDK_ERRLOG("Couldn't find iobuf module: '%s'\n", name);
     319                 :          0 :                 return -ENODEV;
     320                 :            :         }
     321                 :            : 
     322                 :      22531 :         ioch = spdk_get_io_channel(&g_iobuf);
     323         [ +  + ]:      22531 :         if (ioch == NULL) {
     324                 :          0 :                 SPDK_ERRLOG("Couldn't get iobuf IO channel\n");
     325                 :          0 :                 return -ENOMEM;
     326                 :            :         }
     327                 :            : 
     328                 :      22531 :         iobuf_ch = spdk_io_channel_get_ctx(ioch);
     329                 :            : 
     330         [ +  + ]:      44486 :         for (i = 0; i < IOBUF_MAX_CHANNELS; ++i) {
     331   [ +  +  +  -  :      44486 :                 if (iobuf_ch->channels[i] == NULL) {
             +  -  +  + ]
     332   [ +  -  +  -  :      22531 :                         iobuf_ch->channels[i] = ch;
                   +  - ]
     333                 :      22531 :                         break;
     334                 :            :                 }
     335                 :        148 :         }
     336                 :            : 
     337         [ -  + ]:      22531 :         if (i == IOBUF_MAX_CHANNELS) {
     338                 :          0 :                 SPDK_ERRLOG("Max number of iobuf channels (%" PRIu32 ") exceeded.\n", i);
     339                 :          0 :                 goto error;
     340                 :            :         }
     341                 :            : 
     342   [ +  -  +  -  :      22531 :         ch->small.queue = &iobuf_ch->small_queue;
             +  -  +  - ]
     343   [ +  -  +  -  :      22531 :         ch->large.queue = &iobuf_ch->large_queue;
             +  -  +  - ]
     344   [ +  -  +  -  :      22531 :         ch->small.pool = g_iobuf.small_pool;
                   +  - ]
     345   [ +  -  +  -  :      22531 :         ch->large.pool = g_iobuf.large_pool;
             +  -  +  - ]
     346   [ +  -  +  -  :      22531 :         ch->small.bufsize = g_iobuf.opts.small_bufsize;
          +  -  +  -  +  
                      - ]
     347   [ +  -  +  -  :      22531 :         ch->large.bufsize = g_iobuf.opts.large_bufsize;
          +  -  +  -  +  
                      - ]
     348   [ +  -  +  - ]:      22531 :         ch->parent = ioch;
     349   [ +  -  +  - ]:      22531 :         ch->module = module;
     350   [ +  -  +  -  :      22531 :         ch->small.cache_size = small_cache_size;
                   +  - ]
     351   [ +  -  +  -  :      22531 :         ch->large.cache_size = large_cache_size;
                   +  - ]
     352   [ +  -  +  -  :      22531 :         ch->small.cache_count = 0;
                   +  - ]
     353   [ +  -  +  -  :      22531 :         ch->large.cache_count = 0;
                   +  - ]
     354                 :            : 
     355   [ +  -  +  -  :      22531 :         STAILQ_INIT(&ch->small.cache);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     356   [ +  -  +  -  :      22531 :         STAILQ_INIT(&ch->large.cache);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     357                 :            : 
     358         [ +  + ]:    2955342 :         for (i = 0; i < small_cache_size; ++i) {
     359         [ +  + ]:    2932817 :                 if (spdk_ring_dequeue(g_iobuf.small_pool, (void **)&buf, 1) == 0) {
     360   [ #  #  #  # ]:          6 :                         SPDK_ERRLOG("Failed to populate '%s' iobuf small buffer cache at %d/%d entries. "
     361                 :            :                                     "You may need to increase spdk_iobuf_opts.small_pool_count (%"PRIu64")\n",
     362                 :            :                                     name, i, small_cache_size, g_iobuf.opts.small_pool_count);
     363                 :          6 :                         SPDK_ERRLOG("See scripts/calc-iobuf.py for guidance on how to calculate "
     364                 :            :                                     "this value.\n");
     365                 :          6 :                         goto error;
     366                 :            :                 }
     367   [ +  -  +  -  :    2932811 :                 STAILQ_INSERT_TAIL(&ch->small.cache, buf, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     368   [ +  -  +  - ]:    2932811 :                 ch->small.cache_count++;
     369                 :      23038 :         }
     370         [ +  + ]:     416497 :         for (i = 0; i < large_cache_size; ++i) {
     371   [ +  +  +  - ]:     393975 :                 if (spdk_ring_dequeue(g_iobuf.large_pool, (void **)&buf, 1) == 0) {
     372   [ #  #  #  # ]:          3 :                         SPDK_ERRLOG("Failed to populate '%s' iobuf large buffer cache at %d/%d entries. "
     373                 :            :                                     "You may need to increase spdk_iobuf_opts.large_pool_count (%"PRIu64")\n",
     374                 :            :                                     name, i, large_cache_size, g_iobuf.opts.large_pool_count);
     375                 :          3 :                         SPDK_ERRLOG("See scripts/calc-iobuf.py for guidance on how to calculate "
     376                 :            :                                     "this value.\n");
     377                 :          3 :                         goto error;
     378                 :            :                 }
     379   [ +  -  +  -  :     393972 :                 STAILQ_INSERT_TAIL(&ch->large.cache, buf, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     380   [ +  -  +  - ]:     393972 :                 ch->large.cache_count++;
     381                 :       3422 :         }
     382                 :            : 
     383                 :      22522 :         return 0;
     384                 :          9 : error:
     385                 :          9 :         spdk_iobuf_channel_fini(ch);
     386                 :            : 
     387                 :          9 :         return -ENOMEM;
     388                 :        200 : }
     389                 :            : 
     390                 :            : void
     391                 :      22531 : spdk_iobuf_channel_fini(struct spdk_iobuf_channel *ch)
     392                 :            : {
     393                 :            :         struct spdk_iobuf_entry *entry __attribute__((unused));
     394                 :       5950 :         struct spdk_iobuf_buffer *buf;
     395                 :            :         struct iobuf_channel *iobuf_ch;
     396                 :            :         uint32_t i;
     397                 :            : 
     398                 :            :         /* Make sure none of the wait queue entries are coming from this module */
     399   [ +  +  +  -  :      22531 :         STAILQ_FOREACH(entry, ch->small.queue, stailq) {
          +  -  +  -  +  
          -  -  +  #  #  
             #  #  #  # ]
     400   [ #  #  #  #  :          0 :                 assert(entry->module != ch->module);
          #  #  #  #  #  
                #  #  # ]
     401                 :          0 :         }
     402   [ +  +  +  -  :      22531 :         STAILQ_FOREACH(entry, ch->large.queue, stailq) {
          +  -  +  -  +  
          -  -  +  #  #  
             #  #  #  # ]
     403   [ #  #  #  #  :          0 :                 assert(entry->module != ch->module);
          #  #  #  #  #  
                #  #  # ]
     404                 :          0 :         }
     405                 :            : 
     406                 :            :         /* Release cached buffers back to the pool */
     407   [ +  +  +  -  :    2955364 :         while (!STAILQ_EMPTY(&ch->small.cache)) {
          +  -  +  -  +  
                      + ]
     408   [ +  -  +  -  :    2932833 :                 buf = STAILQ_FIRST(&ch->small.cache);
             +  -  +  - ]
     409   [ +  +  +  -  :    2932833 :                 STAILQ_REMOVE_HEAD(&ch->small.cache, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  +  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     410                 :    2932833 :                 spdk_ring_enqueue(g_iobuf.small_pool, (void **)&buf, 1, NULL);
     411   [ +  -  +  - ]:    2932833 :                 ch->small.cache_count--;
     412                 :            :         }
     413   [ +  +  +  -  :     416563 :         while (!STAILQ_EMPTY(&ch->large.cache)) {
          +  -  +  -  +  
                      + ]
     414   [ +  -  +  -  :     394032 :                 buf = STAILQ_FIRST(&ch->large.cache);
             +  -  +  - ]
     415   [ +  +  +  -  :     394032 :                 STAILQ_REMOVE_HEAD(&ch->large.cache, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  +  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     416         [ +  - ]:     394032 :                 spdk_ring_enqueue(g_iobuf.large_pool, (void **)&buf, 1, NULL);
     417   [ +  -  +  - ]:     394032 :                 ch->large.cache_count--;
     418                 :            :         }
     419                 :            : 
     420   [ +  +  +  -  :      22531 :         assert(ch->small.cache_count == 0);
          +  -  +  -  #  
                      # ]
     421   [ +  +  +  -  :      22531 :         assert(ch->large.cache_count == 0);
          +  -  +  -  #  
                      # ]
     422                 :            : 
     423   [ +  -  +  - ]:      22531 :         iobuf_ch = spdk_io_channel_get_ctx(ch->parent);
     424         [ +  + ]:      44486 :         for (i = 0; i < IOBUF_MAX_CHANNELS; ++i) {
     425   [ +  +  +  -  :      44486 :                 if (iobuf_ch->channels[i] == ch) {
             +  -  +  + ]
     426   [ +  -  +  -  :      22531 :                         iobuf_ch->channels[i] = NULL;
                   +  - ]
     427                 :      22531 :                         break;
     428                 :            :                 }
     429                 :        148 :         }
     430                 :            : 
     431   [ +  -  +  - ]:      22531 :         spdk_put_io_channel(ch->parent);
     432   [ +  -  +  - ]:      22531 :         ch->parent = NULL;
     433                 :      22531 : }
     434                 :            : 
     435                 :            : int
     436                 :       4682 : spdk_iobuf_register_module(const char *name)
     437                 :            : {
     438                 :            :         struct iobuf_module *module;
     439                 :            : 
     440   [ +  +  +  -  :       7396 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          +  +  +  -  +  
                -  +  - ]
     441   [ +  +  +  +  :       2715 :                 if (strcmp(name, module->name) == 0) {
          +  +  +  -  +  
                      - ]
     442                 :          1 :                         return -EEXIST;
     443                 :            :                 }
     444                 :        126 :         }
     445                 :            : 
     446                 :       4681 :         module = calloc(1, sizeof(*module));
     447         [ +  + ]:       4681 :         if (module == NULL) {
     448                 :          0 :                 return -ENOMEM;
     449                 :            :         }
     450                 :            : 
     451   [ +  +  +  -  :       4681 :         module->name = strdup(name);
                   +  - ]
     452   [ +  +  +  -  :       4681 :         if (module->name == NULL) {
                   +  - ]
     453                 :          0 :                 free(module);
     454                 :          0 :                 return -ENOMEM;
     455                 :            :         }
     456                 :            : 
     457   [ +  -  +  -  :       4681 :         TAILQ_INSERT_TAIL(&g_iobuf.modules, module, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     458                 :            : 
     459                 :       4681 :         return 0;
     460                 :        150 : }
     461                 :            : 
     462                 :            : int
     463                 :        335 : spdk_iobuf_unregister_module(const char *name)
     464                 :            : {
     465                 :            :         struct iobuf_module *module;
     466                 :            : 
     467   [ +  -  +  -  :       1005 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          +  -  +  -  +  
                -  +  - ]
     468   [ +  +  +  +  :       1005 :                 if (strcmp(name, module->name) == 0) {
          +  +  +  -  +  
                      + ]
     469   [ +  +  +  -  :        335 :                         TAILQ_REMOVE(&g_iobuf.modules, module, tailq);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  -  +  -  
          +  -  +  -  +  
          -  +  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     470   [ +  -  +  - ]:        335 :                         free(module->name);
     471                 :        335 :                         free(module);
     472                 :        335 :                         return 0;
     473                 :            :                 }
     474                 :         68 :         }
     475                 :            : 
     476                 :          0 :         return -ENOENT;
     477                 :         34 : }
     478                 :            : 
     479                 :            : int
     480                 :     195182 : spdk_iobuf_for_each_entry(struct spdk_iobuf_channel *ch, struct spdk_iobuf_pool *pool,
     481                 :            :                           spdk_iobuf_for_each_entry_fn cb_fn, void *cb_ctx)
     482                 :            : {
     483                 :            :         struct spdk_iobuf_entry *entry, *tmp;
     484                 :            :         int rc;
     485                 :            : 
     486   [ +  +  +  -  :     195230 :         STAILQ_FOREACH_SAFE(entry, pool->queue, stailq, tmp) {
          +  -  +  -  +  
          -  #  #  #  #  
             #  #  -  + ]
     487                 :            :                 /* We only want to iterate over the entries requested by the module which owns ch */
     488   [ +  +  #  #  :         48 :                 if (entry->module != ch->module) {
          #  #  #  #  #  
                      # ]
     489                 :         24 :                         continue;
     490                 :            :                 }
     491                 :            : 
     492   [ #  #  #  # ]:         24 :                 rc = cb_fn(ch, entry, cb_ctx);
     493         [ -  + ]:         24 :                 if (rc != 0) {
     494                 :          0 :                         return rc;
     495                 :            :                 }
     496                 :          0 :         }
     497                 :            : 
     498                 :     195182 :         return 0;
     499                 :        188 : }
     500                 :            : 
     501                 :            : void
     502                 :         36 : spdk_iobuf_entry_abort(struct spdk_iobuf_channel *ch, struct spdk_iobuf_entry *entry,
     503                 :            :                        uint64_t len)
     504                 :            : {
     505                 :            :         struct spdk_iobuf_pool *pool;
     506                 :            : 
     507   [ +  +  #  #  :         36 :         if (len <= ch->small.bufsize) {
             #  #  #  # ]
     508         [ #  # ]:         18 :                 pool = &ch->small;
     509                 :          0 :         } else {
     510   [ -  +  #  #  :         18 :                 assert(len <= ch->large.bufsize);
          #  #  #  #  #  
                      # ]
     511         [ #  # ]:         18 :                 pool = &ch->large;
     512                 :            :         }
     513                 :            : 
     514   [ +  -  +  +  :         36 :         STAILQ_REMOVE(pool->queue, entry, spdk_iobuf_entry, stailq);
          -  -  -  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     515                 :         36 : }
     516                 :            : 
     517                 :            : #define IOBUF_BATCH_SIZE 32
     518                 :            : 
     519                 :            : void *
     520                 :   61979098 : spdk_iobuf_get(struct spdk_iobuf_channel *ch, uint64_t len,
     521                 :            :                struct spdk_iobuf_entry *entry, spdk_iobuf_get_cb cb_fn)
     522                 :            : {
     523                 :            :         struct spdk_iobuf_pool *pool;
     524                 :            :         void *buf;
     525                 :            : 
     526   [ +  +  +  -  :   61979098 :         assert(spdk_io_channel_get_thread(ch->parent) == spdk_get_thread());
             +  -  #  # ]
     527   [ +  +  +  -  :   61979098 :         if (len <= ch->small.bufsize) {
             +  -  +  - ]
     528         [ +  - ]:   60193871 :                 pool = &ch->small;
     529                 :       3653 :         } else {
     530   [ -  +  #  #  :    1785227 :                 assert(len <= ch->large.bufsize);
          #  #  #  #  #  
                      # ]
     531         [ #  # ]:    1785227 :                 pool = &ch->large;
     532                 :            :         }
     533                 :            : 
     534   [ +  -  +  -  :   61979098 :         buf = (void *)STAILQ_FIRST(&pool->cache);
                   +  - ]
     535         [ +  + ]:   61979098 :         if (buf) {
     536   [ +  +  +  -  :   53901493 :                 STAILQ_REMOVE_HEAD(&pool->cache, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  -  
          +  #  #  #  #  
          #  #  #  #  #  
                      # ]
     537   [ +  +  +  -  :   53901493 :                 assert(pool->cache_count > 0);
             +  -  #  # ]
     538         [ +  - ]:   53901493 :                 pool->cache_count--;
     539   [ +  -  +  - ]:   53901493 :                 pool->stats.cache++;
     540                 :       3653 :         } else {
     541                 :      39493 :                 struct spdk_iobuf_buffer *bufs[IOBUF_BATCH_SIZE];
     542                 :            :                 size_t sz, i;
     543                 :            : 
     544                 :            :                 /* If we're going to dequeue, we may as well dequeue a batch. */
     545   [ +  +  #  #  :    8077605 :                 sz = spdk_ring_dequeue(pool->pool, (void **)bufs, spdk_min(IOBUF_BATCH_SIZE,
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     546                 :            :                                        spdk_max(pool->cache_size, 1)));
     547         [ +  + ]:    8077605 :                 if (sz == 0) {
     548         [ +  + ]:    7944121 :                         if (entry) {
     549   [ #  #  #  #  :    5929875 :                                 STAILQ_INSERT_TAIL(pool->queue, entry, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     550   [ #  #  #  #  :    5929875 :                                 entry->module = ch->module;
             #  #  #  # ]
     551   [ #  #  #  # ]:    5929875 :                                 entry->cb_fn = cb_fn;
     552   [ #  #  #  # ]:    5929875 :                                 pool->stats.retry++;
     553                 :          0 :                         }
     554                 :            : 
     555                 :    7944121 :                         return NULL;
     556                 :            :                 }
     557                 :            : 
     558   [ #  #  #  # ]:     133484 :                 pool->stats.main++;
     559         [ +  + ]:    3784692 :                 for (i = 0; i < (sz - 1); i++) {
     560   [ +  +  #  #  :    3651208 :                         STAILQ_INSERT_HEAD(&pool->cache, bufs[i], stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     561         [ #  # ]:    3651208 :                         pool->cache_count++;
     562                 :          0 :                 }
     563                 :            : 
     564                 :            :                 /* The last one is the one we'll return */
     565   [ #  #  #  #  :     133484 :                 buf = bufs[i];
                   #  # ]
     566                 :            :         }
     567                 :            : 
     568                 :   54034977 :         return (char *)buf;
     569                 :       3653 : }
     570                 :            : 
     571                 :            : void
     572                 :   59964816 : spdk_iobuf_put(struct spdk_iobuf_channel *ch, void *buf, uint64_t len)
     573                 :            : {
     574                 :            :         struct spdk_iobuf_entry *entry;
     575                 :            :         struct spdk_iobuf_buffer *iobuf_buf;
     576                 :            :         struct spdk_iobuf_pool *pool;
     577                 :            :         size_t sz;
     578                 :            : 
     579   [ +  +  +  -  :   59964816 :         assert(spdk_io_channel_get_thread(ch->parent) == spdk_get_thread());
             +  -  #  # ]
     580   [ +  +  +  -  :   59964816 :         if (len <= ch->small.bufsize) {
             +  -  +  - ]
     581         [ +  - ]:   58179607 :                 pool = &ch->small;
     582                 :       3653 :         } else {
     583         [ #  # ]:    1785209 :                 pool = &ch->large;
     584                 :            :         }
     585                 :            : 
     586   [ +  +  +  -  :   59964816 :         if (STAILQ_EMPTY(pool->queue)) {
          +  -  +  -  -  
                      + ]
     587   [ +  +  +  -  :   54034977 :                 if (pool->cache_size == 0) {
                   +  - ]
     588   [ #  #  #  # ]:         54 :                         spdk_ring_enqueue(pool->pool, (void **)&buf, 1, NULL);
     589                 :         54 :                         return;
     590                 :            :                 }
     591                 :            : 
     592                 :   54034923 :                 iobuf_buf = (struct spdk_iobuf_buffer *)buf;
     593                 :            : 
     594   [ +  +  +  -  :   54034923 :                 STAILQ_INSERT_HEAD(&pool->cache, iobuf_buf, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          #  #  #  #  #  
          #  #  #  #  #  
          +  -  +  -  +  
                      - ]
     595         [ +  - ]:   54034923 :                 pool->cache_count++;
     596                 :            : 
     597                 :            :                 /* The cache size may exceed the configured amount. We always dequeue from the
     598                 :            :                  * central pool in batches of known size, so wait until at least a batch
     599                 :            :                  * has been returned to actually return the buffers to the central pool. */
     600   [ +  -  +  -  :   54034923 :                 sz = spdk_min(IOBUF_BATCH_SIZE, pool->cache_size);
          -  +  +  -  +  
                      - ]
     601   [ +  +  +  -  :   54034923 :                 if (pool->cache_count >= pool->cache_size + sz) {
          +  -  +  -  +  
                      - ]
     602                 :       8971 :                         struct spdk_iobuf_buffer *bufs[IOBUF_BATCH_SIZE];
     603                 :            :                         size_t i;
     604                 :            : 
     605         [ +  + ]:    3917974 :                         for (i = 0; i < sz; i++) {
     606   [ #  #  #  #  :    3784556 :                                 bufs[i] = STAILQ_FIRST(&pool->cache);
          #  #  #  #  #  
                #  #  # ]
     607   [ -  +  #  #  :    3784556 :                                 STAILQ_REMOVE_HEAD(&pool->cache, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     608   [ -  +  #  #  :    3784556 :                                 assert(pool->cache_count > 0);
             #  #  #  # ]
     609         [ #  # ]:    3784556 :                                 pool->cache_count--;
     610                 :          0 :                         }
     611                 :            : 
     612   [ #  #  #  # ]:     133418 :                         spdk_ring_enqueue(pool->pool, (void **)bufs, sz, NULL);
     613                 :          0 :                 }
     614                 :       3653 :         } else {
     615   [ #  #  #  #  :    5929839 :                 entry = STAILQ_FIRST(pool->queue);
             #  #  #  # ]
     616   [ +  +  #  #  :    5929839 :                 STAILQ_REMOVE_HEAD(pool->queue, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     617   [ #  #  #  #  :    5929839 :                 entry->cb_fn(entry, buf);
             #  #  #  # ]
     618   [ +  +  +  +  :    5929839 :                 if (spdk_unlikely(entry == STAILQ_LAST(pool->queue, spdk_iobuf_entry, stailq))) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     619   [ +  +  +  -  :  924314737 :                         STAILQ_REMOVE(pool->queue, entry, spdk_iobuf_entry, stailq);
          +  +  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     620   [ +  +  #  #  :    5519474 :                         STAILQ_INSERT_HEAD(pool->queue, entry, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     621                 :          0 :                 }
     622                 :            :         }
     623                 :       3653 : }
     624                 :            : 
     625                 :            : static void
     626                 :          3 : iobuf_get_channel_stats_done(struct spdk_io_channel_iter *iter, int status)
     627                 :            : {
     628                 :          3 :         struct iobuf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(iter);
     629                 :            : 
     630   [ #  #  #  #  :          3 :         ctx->cb_fn(ctx->modules, ctx->num_modules, ctx->cb_arg);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     631   [ #  #  #  # ]:          3 :         free(ctx->modules);
     632                 :          3 :         free(ctx);
     633                 :          3 : }
     634                 :            : 
     635                 :            : static void
     636                 :          3 : iobuf_get_channel_stats(struct spdk_io_channel_iter *iter)
     637                 :            : {
     638                 :          3 :         struct iobuf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(iter);
     639                 :          3 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(iter);
     640                 :          3 :         struct iobuf_channel *iobuf_ch = spdk_io_channel_get_ctx(ch);
     641                 :            :         struct spdk_iobuf_channel *channel;
     642                 :            :         struct iobuf_module *module;
     643                 :            :         struct spdk_iobuf_module_stats *it;
     644                 :            :         uint32_t i, j;
     645                 :            : 
     646   [ +  +  #  #  :         12 :         for (i = 0; i < ctx->num_modules; ++i) {
                   #  # ]
     647         [ +  - ]:         18 :                 for (j = 0; j < IOBUF_MAX_CHANNELS; ++j) {
     648   [ #  #  #  #  :         18 :                         channel = iobuf_ch->channels[j];
                   #  # ]
     649         [ -  + ]:         18 :                         if (channel == NULL) {
     650                 :          0 :                                 continue;
     651                 :            :                         }
     652                 :            : 
     653   [ #  #  #  #  :         18 :                         it = &ctx->modules[i];
                   #  # ]
     654   [ #  #  #  # ]:         18 :                         module = (struct iobuf_module *)channel->module;
     655   [ -  +  -  +  :         18 :                         if (strcmp(it->module, module->name) == 0) {
          +  +  #  #  #  
             #  #  #  #  
                      # ]
     656   [ #  #  #  #  :          9 :                                 it->small_pool.cache += channel->small.stats.cache;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     657   [ #  #  #  #  :          9 :                                 it->small_pool.main += channel->small.stats.main;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     658   [ #  #  #  #  :          9 :                                 it->small_pool.retry += channel->small.stats.retry;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     659   [ #  #  #  #  :          9 :                                 it->large_pool.cache += channel->large.stats.cache;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     660   [ #  #  #  #  :          9 :                                 it->large_pool.main += channel->large.stats.main;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     661   [ #  #  #  #  :          9 :                                 it->large_pool.retry += channel->large.stats.retry;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     662                 :          9 :                                 break;
     663                 :            :                         }
     664                 :          0 :                 }
     665                 :          0 :         }
     666                 :            : 
     667                 :          3 :         spdk_for_each_channel_continue(iter, 0);
     668                 :          3 : }
     669                 :            : 
     670                 :            : int
     671                 :          3 : spdk_iobuf_get_stats(spdk_iobuf_get_stats_cb cb_fn, void *cb_arg)
     672                 :            : {
     673                 :            :         struct iobuf_module *module;
     674                 :            :         struct iobuf_get_stats_ctx *ctx;
     675                 :            :         uint32_t i;
     676                 :            : 
     677                 :          3 :         ctx = calloc(1, sizeof(*ctx));
     678         [ -  + ]:          3 :         if (ctx == NULL) {
     679                 :          0 :                 return -ENOMEM;
     680                 :            :         }
     681                 :            : 
     682   [ +  +  #  #  :         12 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          #  #  #  #  #  
                #  #  # ]
     683         [ #  # ]:          9 :                 ++ctx->num_modules;
     684                 :          0 :         }
     685                 :            : 
     686   [ #  #  #  #  :          3 :         ctx->modules = calloc(ctx->num_modules, sizeof(struct spdk_iobuf_module_stats));
             #  #  #  # ]
     687   [ -  +  #  #  :          3 :         if (ctx->modules == NULL) {
                   #  # ]
     688                 :          0 :                 free(ctx);
     689                 :          0 :                 return -ENOMEM;
     690                 :            :         }
     691                 :            : 
     692                 :          3 :         i = 0;
     693   [ +  +  #  #  :         12 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          #  #  #  #  #  
                #  #  # ]
     694   [ #  #  #  #  :          9 :                 ctx->modules[i].module = module->name;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     695                 :          9 :                 ++i;
     696                 :          0 :         }
     697                 :            : 
     698   [ #  #  #  # ]:          3 :         ctx->cb_fn = cb_fn;
     699   [ #  #  #  # ]:          3 :         ctx->cb_arg = cb_arg;
     700                 :            : 
     701                 :          3 :         spdk_for_each_channel(&g_iobuf, iobuf_get_channel_stats, ctx,
     702                 :            :                               iobuf_get_channel_stats_done);
     703                 :          3 :         return 0;
     704                 :          0 : }

Generated by: LCOV version 1.15