LCOV - code coverage report
Current view: top level - spdk/lib/thread - iobuf.c (source / functions) Hit Total Coverage
Test: Combined Lines: 398 477 83.4 %
Date: 2024-12-07 01:11:51 Functions: 25 25 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 866 2296 37.7 %

           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_node {
      33                 :            :         spdk_iobuf_entry_stailq_t       small_queue;
      34                 :            :         spdk_iobuf_entry_stailq_t       large_queue;
      35                 :            : };
      36                 :            : 
      37                 :            : struct iobuf_channel {
      38                 :            :         struct iobuf_channel_node       node[SPDK_CONFIG_MAX_NUMA_NODES];
      39                 :            :         struct spdk_iobuf_channel       *channels[IOBUF_MAX_CHANNELS];
      40                 :            : };
      41                 :            : 
      42                 :            : struct iobuf_module {
      43                 :            :         char                            *name;
      44                 :            :         TAILQ_ENTRY(iobuf_module)       tailq;
      45                 :            : };
      46                 :            : 
      47                 :            : struct iobuf_node {
      48                 :            :         struct spdk_ring                *small_pool;
      49                 :            :         struct spdk_ring                *large_pool;
      50                 :            :         void                            *small_pool_base;
      51                 :            :         void                            *large_pool_base;
      52                 :            : };
      53                 :            : 
      54                 :            : struct iobuf {
      55                 :            :         struct spdk_iobuf_opts          opts;
      56                 :            :         TAILQ_HEAD(, iobuf_module)      modules;
      57                 :            :         spdk_iobuf_finish_cb            finish_cb;
      58                 :            :         void                            *finish_arg;
      59                 :            :         struct iobuf_node               node[SPDK_CONFIG_MAX_NUMA_NODES];
      60                 :            : };
      61                 :            : 
      62                 :            : #define IOBUF_FOREACH_NUMA_ID(i)                                                \
      63                 :            :         for (i = g_iobuf.opts.enable_numa ? spdk_env_get_first_numa_id() : 0;   \
      64                 :            :              i < INT32_MAX;                                                  \
      65                 :            :              i = g_iobuf.opts.enable_numa ? spdk_env_get_next_numa_id(i) : INT32_MAX)
      66                 :            : 
      67                 :            : static struct iobuf g_iobuf = {
      68                 :            :         .modules = TAILQ_HEAD_INITIALIZER(g_iobuf.modules),
      69                 :            :         .node = {},
      70                 :            :         .opts = {
      71                 :            :                 .small_pool_count = IOBUF_DEFAULT_SMALL_POOL_SIZE,
      72                 :            :                 .large_pool_count = IOBUF_DEFAULT_LARGE_POOL_SIZE,
      73                 :            :                 .small_bufsize = IOBUF_DEFAULT_SMALL_BUFSIZE,
      74                 :            :                 .large_bufsize = IOBUF_DEFAULT_LARGE_BUFSIZE,
      75                 :            :         },
      76                 :            : };
      77                 :            : 
      78                 :            : struct iobuf_get_stats_ctx {
      79                 :            :         struct spdk_iobuf_module_stats  *modules;
      80                 :            :         uint32_t                        num_modules;
      81                 :            :         spdk_iobuf_get_stats_cb         cb_fn;
      82                 :            :         void                            *cb_arg;
      83                 :            : };
      84                 :            : 
      85                 :            : static int
      86                 :       7478 : iobuf_channel_create_cb(void *io_device, void *ctx)
      87                 :            : {
      88                 :       7478 :         struct iobuf_channel *ch = ctx;
      89                 :            :         struct iobuf_channel_node *node;
      90                 :            :         int32_t i;
      91                 :            : 
      92   [ +  +  +  +  :      14956 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  +  -  -  
                      + ]
      93   [ +  -  +  -  :       7478 :                 node = &ch->node[i];
                   +  - ]
      94   [ +  -  +  -  :       7478 :                 STAILQ_INIT(&node->small_queue);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      95   [ +  +  +  -  :       7478 :                 STAILQ_INIT(&node->large_queue);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
      96                 :        452 :         }
      97                 :            : 
      98                 :       7478 :         return 0;
      99                 :            : }
     100                 :            : 
     101                 :            : static void
     102                 :       7478 : iobuf_channel_destroy_cb(void *io_device, void *ctx)
     103                 :            : {
     104                 :       7478 :         struct iobuf_channel *ch = ctx;
     105                 :            :         struct iobuf_channel_node *node __attribute__((unused));
     106                 :            :         int32_t i;
     107                 :            : 
     108   [ +  +  +  +  :      14956 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  +  -  -  
                      + ]
     109   [ +  -  +  -  :       7478 :                 node = &ch->node[i];
                   +  - ]
     110   [ +  +  +  -  :       7478 :                 assert(STAILQ_EMPTY(&node->small_queue));
          +  -  +  -  #  
                      # ]
     111   [ +  +  +  -  :       7478 :                 assert(STAILQ_EMPTY(&node->large_queue));
          +  -  +  -  #  
                      # ]
     112                 :        452 :         }
     113                 :       7478 : }
     114                 :            : 
     115                 :            : static int
     116                 :       2415 : iobuf_node_initialize(struct iobuf_node *node, uint32_t numa_id)
     117                 :            : {
     118                 :       2415 :         struct spdk_iobuf_opts *opts = &g_iobuf.opts;
     119                 :       1046 :         struct spdk_iobuf_buffer *buf;
     120                 :            :         uint64_t i;
     121                 :            :         int rc;
     122                 :            : 
     123   [ +  +  -  + ]:       2415 :         if (!g_iobuf.opts.enable_numa) {
     124                 :       2415 :                 numa_id = SPDK_ENV_NUMA_ID_ANY;
     125                 :        166 :         }
     126                 :            : 
     127   [ +  -  +  -  :       2523 :         node->small_pool = spdk_ring_create(SPDK_RING_TYPE_MP_MC, opts->small_pool_count,
          +  -  +  -  +  
                      - ]
     128                 :        166 :                                             numa_id);
     129   [ +  +  +  -  :       2415 :         if (!node->small_pool) {
                   +  - ]
     130                 :          0 :                 SPDK_ERRLOG("Failed to create small iobuf pool\n");
     131                 :          0 :                 rc = -ENOMEM;
     132                 :          0 :                 goto error;
     133                 :            :         }
     134                 :            : 
     135   [ +  -  +  -  :       2523 :         node->small_pool_base = spdk_malloc(opts->small_bufsize * opts->small_pool_count, IOBUF_ALIGNMENT,
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     136                 :        166 :                                             NULL, numa_id, SPDK_MALLOC_DMA);
     137   [ +  +  +  -  :       2415 :         if (node->small_pool_base == NULL) {
                   +  - ]
     138                 :          0 :                 SPDK_ERRLOG("Unable to allocate requested small iobuf pool size\n");
     139                 :          0 :                 rc = -ENOMEM;
     140                 :          0 :                 goto error;
     141                 :            :         }
     142                 :            : 
     143   [ +  -  +  -  :       2523 :         node->large_pool = spdk_ring_create(SPDK_RING_TYPE_MP_MC, opts->large_pool_count,
          +  -  +  -  +  
                      - ]
     144                 :        166 :                                             numa_id);
     145   [ +  +  +  -  :       2415 :         if (!node->large_pool) {
                   +  - ]
     146                 :          0 :                 SPDK_ERRLOG("Failed to create large iobuf pool\n");
     147                 :          0 :                 rc = -ENOMEM;
     148                 :          0 :                 goto error;
     149                 :            :         }
     150                 :            : 
     151   [ -  +  -  +  :       2523 :         node->large_pool_base = spdk_malloc(opts->large_bufsize * opts->large_pool_count, IOBUF_ALIGNMENT,
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     152                 :        166 :                                             NULL, numa_id, SPDK_MALLOC_DMA);
     153   [ -  +  -  +  :       2415 :         if (node->large_pool_base == NULL) {
                   +  - ]
     154                 :          0 :                 SPDK_ERRLOG("Unable to allocate requested large iobuf pool size\n");
     155                 :          0 :                 rc = -ENOMEM;
     156                 :          0 :                 goto error;
     157                 :            :         }
     158                 :            : 
     159   [ +  +  +  -  :   19792407 :         for (i = 0; i < opts->small_pool_count; i++) {
                   +  + ]
     160   [ +  -  +  -  :   19789992 :                 buf = node->small_pool_base + i * opts->small_bufsize;
             +  -  +  - ]
     161   [ +  -  +  - ]:   19789992 :                 spdk_ring_enqueue(node->small_pool, (void **)&buf, 1, NULL);
     162                 :    1349768 :         }
     163                 :            : 
     164   [ +  +  +  -  :    2472601 :         for (i = 0; i < opts->large_pool_count; i++) {
                   +  + ]
     165   [ +  -  +  -  :    2470186 :                 buf = node->large_pool_base + i * opts->large_bufsize;
             +  -  +  - ]
     166   [ +  -  +  - ]:    2470186 :                 spdk_ring_enqueue(node->large_pool, (void **)&buf, 1, NULL);
     167                 :     167528 :         }
     168                 :            : 
     169                 :       2415 :         return 0;
     170                 :            : 
     171                 :          0 : error:
     172   [ #  #  #  # ]:          0 :         spdk_free(node->small_pool_base);
     173   [ #  #  #  # ]:          0 :         spdk_ring_free(node->small_pool);
     174   [ #  #  #  # ]:          0 :         spdk_free(node->large_pool_base);
     175   [ #  #  #  # ]:          0 :         spdk_ring_free(node->large_pool);
     176         [ #  # ]:          0 :         memset(node, 0, sizeof(*node));
     177                 :            : 
     178                 :          0 :         return rc;
     179                 :        166 : }
     180                 :            : 
     181                 :            : static void
     182                 :       2415 : iobuf_node_free(struct iobuf_node *node)
     183                 :            : {
     184   [ +  +  +  -  :       2415 :         if (node->small_pool == NULL) {
                   +  - ]
     185                 :            :                 /* This node didn't get allocated, so just return immediately. */
     186                 :          0 :                 return;
     187                 :            :         }
     188                 :            : 
     189   [ +  +  +  -  :       2415 :         if (spdk_ring_count(node->small_pool) != g_iobuf.opts.small_pool_count) {
                   +  - ]
     190   [ #  #  #  # ]:         28 :                 SPDK_ERRLOG("small iobuf pool count is %zu, expected %"PRIu64"\n",
     191                 :            :                             spdk_ring_count(node->small_pool), g_iobuf.opts.small_pool_count);
     192                 :          7 :         }
     193                 :            : 
     194   [ +  +  +  -  :       2415 :         if (spdk_ring_count(node->large_pool) != g_iobuf.opts.large_pool_count) {
             +  -  +  - ]
     195   [ #  #  #  #  :          8 :                 SPDK_ERRLOG("large iobuf pool count is %zu, expected %"PRIu64"\n",
                   #  # ]
     196                 :            :                             spdk_ring_count(node->large_pool), g_iobuf.opts.large_pool_count);
     197                 :          2 :         }
     198                 :            : 
     199   [ +  -  +  - ]:       2415 :         spdk_free(node->small_pool_base);
     200   [ +  -  +  - ]:       2415 :         node->small_pool_base = NULL;
     201   [ +  -  +  - ]:       2415 :         spdk_ring_free(node->small_pool);
     202   [ +  -  +  - ]:       2415 :         node->small_pool = NULL;
     203                 :            : 
     204   [ +  -  +  - ]:       2415 :         spdk_free(node->large_pool_base);
     205   [ +  -  +  - ]:       2415 :         node->large_pool_base = NULL;
     206   [ +  -  +  - ]:       2415 :         spdk_ring_free(node->large_pool);
     207   [ +  -  +  - ]:       2415 :         node->large_pool = NULL;
     208                 :        166 : }
     209                 :            : 
     210                 :            : int
     211                 :       2415 : spdk_iobuf_initialize(void)
     212                 :            : {
     213                 :       2415 :         struct spdk_iobuf_opts *opts = &g_iobuf.opts;
     214                 :            :         struct iobuf_node *node;
     215                 :            :         int32_t i;
     216                 :       2415 :         int rc = 0;
     217                 :            : 
     218                 :            :         /* Round up to the nearest alignment so that each element remains aligned */
     219   [ +  -  +  -  :       2415 :         opts->small_bufsize = SPDK_ALIGN_CEIL(opts->small_bufsize, IOBUF_ALIGNMENT);
             +  -  +  - ]
     220   [ +  -  +  -  :       2415 :         opts->large_bufsize = SPDK_ALIGN_CEIL(opts->large_bufsize, IOBUF_ALIGNMENT);
             +  -  +  - ]
     221                 :            : 
     222   [ +  +  +  +  :       4830 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  +  -  -  
                      + ]
     223         [ +  - ]:       2415 :                 node = &g_iobuf.node[i];
     224                 :       2415 :                 rc = iobuf_node_initialize(node, i);
     225         [ +  + ]:       2415 :                 if (rc) {
     226                 :          0 :                         goto err;
     227                 :            :                 }
     228                 :        166 :         }
     229                 :            : 
     230                 :       2415 :         spdk_io_device_register(&g_iobuf, iobuf_channel_create_cb, iobuf_channel_destroy_cb,
     231                 :            :                                 sizeof(struct iobuf_channel), "iobuf");
     232                 :       2415 :         g_iobuf_is_initialized = true;
     233                 :            : 
     234                 :       2415 :         return 0;
     235                 :            : 
     236                 :          0 : err:
     237   [ #  #  #  #  :          0 :         IOBUF_FOREACH_NUMA_ID(i) {
          #  #  #  #  #  
                      # ]
     238         [ #  # ]:          0 :                 node = &g_iobuf.node[i];
     239                 :          0 :                 iobuf_node_free(node);
     240                 :          0 :         }
     241                 :          0 :         return rc;
     242                 :        166 : }
     243                 :            : 
     244                 :            : static void
     245                 :       2415 : iobuf_unregister_cb(void *io_device)
     246                 :            : {
     247                 :            :         struct iobuf_module *module;
     248                 :            :         struct iobuf_node *node;
     249                 :            :         int32_t i;
     250                 :            : 
     251   [ +  +  +  -  :       6898 :         while (!TAILQ_EMPTY(&g_iobuf.modules)) {
                   +  + ]
     252   [ +  -  +  - ]:       4483 :                 module = TAILQ_FIRST(&g_iobuf.modules);
     253   [ +  +  +  -  :       4483 :                 TAILQ_REMOVE(&g_iobuf.modules, module, tailq);
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     254   [ +  -  +  - ]:       4483 :                 free(module->name);
     255                 :       4483 :                 free(module);
     256                 :            :         }
     257                 :            : 
     258   [ +  +  +  +  :       4830 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  +  -  -  
                      + ]
     259         [ +  - ]:       2415 :                 node = &g_iobuf.node[i];
     260                 :       2415 :                 iobuf_node_free(node);
     261                 :        166 :         }
     262                 :            : 
     263   [ +  +  +  - ]:       2415 :         if (g_iobuf.finish_cb != NULL) {
     264   [ +  -  -  +  :       2415 :                 g_iobuf.finish_cb(g_iobuf.finish_arg);
             +  -  +  - ]
     265                 :        166 :         }
     266                 :       2415 : }
     267                 :            : 
     268                 :            : void
     269                 :       2415 : spdk_iobuf_finish(spdk_iobuf_finish_cb cb_fn, void *cb_arg)
     270                 :            : {
     271   [ +  +  +  + ]:       2415 :         if (!g_iobuf_is_initialized) {
     272   [ #  #  #  # ]:          0 :                 cb_fn(cb_arg);
     273                 :          0 :                 return;
     274                 :            :         }
     275                 :            : 
     276                 :       2415 :         g_iobuf_is_initialized = false;
     277         [ +  - ]:       2415 :         g_iobuf.finish_cb = cb_fn;
     278         [ +  - ]:       2415 :         g_iobuf.finish_arg = cb_arg;
     279                 :            : 
     280                 :       2415 :         spdk_io_device_unregister(&g_iobuf, iobuf_unregister_cb);
     281                 :        166 : }
     282                 :            : 
     283                 :            : int
     284                 :        233 : spdk_iobuf_set_opts(const struct spdk_iobuf_opts *opts)
     285                 :            : {
     286         [ +  + ]:        233 :         if (!opts) {
     287                 :          0 :                 SPDK_ERRLOG("opts cannot be NULL\n");
     288                 :          0 :                 return -1;
     289                 :            :         }
     290                 :            : 
     291   [ +  +  +  -  :        233 :         if (!opts->opts_size) {
                   +  - ]
     292                 :          0 :                 SPDK_ERRLOG("opts_size inside opts cannot be zero value\n");
     293                 :          0 :                 return -1;
     294                 :            :         }
     295                 :            : 
     296   [ +  +  +  -  :        233 :         if (opts->small_pool_count < IOBUF_MIN_SMALL_POOL_SIZE) {
                   -  + ]
     297                 :          0 :                 SPDK_ERRLOG("small_pool_count must be at least %" PRIu32 "\n",
     298                 :            :                             IOBUF_MIN_SMALL_POOL_SIZE);
     299                 :          0 :                 return -EINVAL;
     300                 :            :         }
     301   [ +  +  +  -  :        233 :         if (opts->large_pool_count < IOBUF_MIN_LARGE_POOL_SIZE) {
                   -  + ]
     302                 :          0 :                 SPDK_ERRLOG("large_pool_count must be at least %" PRIu32 "\n",
     303                 :            :                             IOBUF_MIN_LARGE_POOL_SIZE);
     304                 :          0 :                 return -EINVAL;
     305                 :            :         }
     306                 :            : 
     307   [ +  +  +  -  :        233 :         if (opts->small_bufsize < IOBUF_MIN_SMALL_BUFSIZE) {
                   -  + ]
     308                 :          0 :                 SPDK_ERRLOG("small_bufsize must be at least %" PRIu32 "\n",
     309                 :            :                             IOBUF_MIN_SMALL_BUFSIZE);
     310                 :          0 :                 return -EINVAL;
     311                 :            :         }
     312                 :            : 
     313   [ +  +  +  -  :        233 :         if (opts->large_bufsize < IOBUF_MIN_LARGE_BUFSIZE) {
                   -  + ]
     314                 :          0 :                 SPDK_ERRLOG("large_bufsize must be at least %" PRIu32 "\n",
     315                 :            :                             IOBUF_MIN_LARGE_BUFSIZE);
     316                 :          0 :                 return -EINVAL;
     317                 :            :         }
     318                 :            : 
     319   [ +  +  +  -  :        233 :         if (opts->enable_numa &&
             -  +  #  # ]
     320                 :          0 :             spdk_env_get_last_numa_id() >= SPDK_CONFIG_MAX_NUMA_NODES) {
     321                 :          0 :                 SPDK_ERRLOG("max NUMA ID %" PRIu32 " cannot be supported with "
     322                 :            :                             "SPDK_CONFIG_MAX_NUMA_NODES %" PRIu32 "\n",
     323                 :            :                             spdk_env_get_last_numa_id(), SPDK_CONFIG_MAX_NUMA_NODES);
     324         [ #  # ]:          0 :                 SPDK_ERRLOG("Re-configure with --max-numa-nodes=%" PRIu32 "\n",
     325                 :            :                             spdk_env_get_last_numa_id() + 1);
     326                 :          0 :                 return -EINVAL;
     327                 :            :         }
     328                 :            : 
     329                 :            : #define SET_FIELD(field) \
     330                 :            :         if (offsetof(struct spdk_iobuf_opts, field) + sizeof(opts->field) <= opts->opts_size) { \
     331                 :            :                 g_iobuf.opts.field = opts->field; \
     332                 :            :         } \
     333                 :            : 
     334   [ +  +  +  -  :        233 :         SET_FIELD(small_pool_count);
          -  +  +  -  +  
                      - ]
     335   [ +  +  +  -  :        233 :         SET_FIELD(large_pool_count);
          -  +  +  -  +  
                -  +  - ]
     336   [ +  +  +  -  :        233 :         SET_FIELD(small_bufsize);
          -  +  +  -  +  
                -  +  - ]
     337   [ +  +  +  -  :        233 :         SET_FIELD(large_bufsize);
          -  +  +  -  +  
                -  +  - ]
     338   [ +  +  +  -  :        233 :         SET_FIELD(enable_numa);
          -  +  +  -  +  
                -  +  - ]
     339                 :            : 
     340   [ +  -  +  -  :        233 :         g_iobuf.opts.opts_size = opts->opts_size;
                   +  - ]
     341                 :            : 
     342                 :            : #undef SET_FIELD
     343                 :            : 
     344                 :        233 :         return 0;
     345                 :         16 : }
     346                 :            : 
     347                 :            : void
     348                 :       8528 : spdk_iobuf_get_opts(struct spdk_iobuf_opts *opts, size_t opts_size)
     349                 :            : {
     350         [ +  + ]:       8528 :         if (!opts) {
     351                 :          0 :                 SPDK_ERRLOG("opts should not be NULL\n");
     352                 :          0 :                 return;
     353                 :            :         }
     354                 :            : 
     355         [ +  + ]:       8528 :         if (!opts_size) {
     356                 :          0 :                 SPDK_ERRLOG("opts_size should not be zero value\n");
     357                 :          0 :                 return;
     358                 :            :         }
     359                 :            : 
     360   [ +  -  +  - ]:       8528 :         opts->opts_size = opts_size;
     361                 :            : 
     362                 :            : #define SET_FIELD(field) \
     363                 :            :         if (offsetof(struct spdk_iobuf_opts, field) + sizeof(opts->field) <= opts_size) { \
     364                 :            :                 opts->field = g_iobuf.opts.field; \
     365                 :            :         } \
     366                 :            : 
     367   [ +  +  +  -  :       8528 :         SET_FIELD(small_pool_count);
                   +  - ]
     368   [ +  +  +  -  :       8528 :         SET_FIELD(large_pool_count);
             +  -  +  - ]
     369   [ +  +  +  -  :       8528 :         SET_FIELD(small_bufsize);
             +  -  +  - ]
     370   [ +  +  +  -  :       8528 :         SET_FIELD(large_bufsize);
             +  -  +  - ]
     371   [ +  +  +  -  :       8528 :         SET_FIELD(enable_numa);
             +  -  +  - ]
     372                 :            : 
     373                 :            : #undef SET_FIELD
     374                 :            : 
     375                 :            :         /* Do not remove this statement, you should always update this statement when you adding a new field,
     376                 :            :          * and do not forget to add the SET_FIELD statement for your added field. */
     377                 :            :         SPDK_STATIC_ASSERT(sizeof(struct spdk_iobuf_opts) == 40, "Incorrect size");
     378                 :        553 : }
     379                 :            : 
     380                 :            : static void
     381                 :      22993 : iobuf_channel_node_init(struct spdk_iobuf_channel *ch, struct iobuf_channel *iobuf_ch,
     382                 :            :                         int32_t numa_id, uint32_t small_cache_size, uint32_t large_cache_size)
     383                 :            : {
     384         [ +  - ]:      22993 :         struct iobuf_node *node = &g_iobuf.node[numa_id];
     385   [ +  -  +  - ]:      22993 :         struct spdk_iobuf_node_cache *cache = &ch->cache[numa_id];
     386   [ +  -  +  -  :      22993 :         struct iobuf_channel_node *ch_node = &iobuf_ch->node[numa_id];
                   +  - ]
     387                 :            : 
     388   [ +  -  +  -  :      22993 :         cache->small.queue = &ch_node->small_queue;
             +  -  +  - ]
     389   [ +  -  +  -  :      22993 :         cache->large.queue = &ch_node->large_queue;
             +  -  +  - ]
     390   [ +  -  +  -  :      22993 :         cache->small.pool = node->small_pool;
          +  -  +  -  +  
                      - ]
     391   [ +  -  +  -  :      22993 :         cache->large.pool = node->large_pool;
          +  -  +  -  +  
                      - ]
     392   [ +  -  +  -  :      22993 :         cache->small.bufsize = g_iobuf.opts.small_bufsize;
             +  -  +  - ]
     393   [ +  -  +  -  :      22993 :         cache->large.bufsize = g_iobuf.opts.large_bufsize;
             +  -  +  - ]
     394   [ +  -  +  -  :      22993 :         cache->small.cache_size = small_cache_size;
                   +  - ]
     395   [ +  -  +  -  :      22993 :         cache->large.cache_size = large_cache_size;
                   +  - ]
     396   [ +  -  +  -  :      22993 :         cache->small.cache_count = 0;
                   +  - ]
     397   [ +  -  +  -  :      22993 :         cache->large.cache_count = 0;
                   +  - ]
     398                 :            : 
     399   [ +  -  +  -  :      22993 :         STAILQ_INIT(&cache->small.cache);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     400   [ +  -  +  -  :      22993 :         STAILQ_INIT(&cache->large.cache);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     401                 :      22993 : }
     402                 :            : 
     403                 :            : static int
     404                 :      22993 : iobuf_channel_node_populate(struct spdk_iobuf_channel *ch, const char *name, int32_t numa_id)
     405                 :            : {
     406         [ +  - ]:      22993 :         struct iobuf_node *node = &g_iobuf.node[numa_id];
     407   [ +  -  +  - ]:      22993 :         struct spdk_iobuf_node_cache *cache = &ch->cache[numa_id];
     408   [ +  -  +  -  :      22993 :         uint32_t small_cache_size = cache->small.cache_size;
                   +  - ]
     409   [ +  -  +  -  :      22993 :         uint32_t large_cache_size = cache->large.cache_size;
                   +  - ]
     410                 :       5922 :         struct spdk_iobuf_buffer *buf;
     411                 :            :         uint32_t i;
     412                 :            : 
     413         [ +  + ]:    3019321 :         for (i = 0; i < small_cache_size; ++i) {
     414   [ +  +  +  -  :    2996336 :                 if (spdk_ring_dequeue(node->small_pool, (void **)&buf, 1) == 0) {
                   -  + ]
     415                 :          8 :                         SPDK_ERRLOG("Failed to populate '%s' iobuf small buffer cache at %d/%d entries. "
     416                 :            :                                     "You may need to increase spdk_iobuf_opts.small_pool_count (%"PRIu64")\n",
     417                 :            :                                     name, i, small_cache_size, g_iobuf.opts.small_pool_count);
     418                 :          8 :                         SPDK_ERRLOG("See scripts/calc-iobuf.py for guidance on how to calculate "
     419                 :            :                                     "this value.\n");
     420                 :          8 :                         return -ENOMEM;
     421                 :            :                 }
     422   [ +  -  +  -  :    2996328 :                 STAILQ_INSERT_TAIL(&cache->small.cache, buf, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     423   [ +  -  +  - ]:    2996328 :                 cache->small.cache_count++;
     424                 :     107007 :         }
     425         [ +  + ]:     427012 :         for (i = 0; i < large_cache_size; ++i) {
     426   [ +  +  +  -  :     404031 :                 if (spdk_ring_dequeue(node->large_pool, (void **)&buf, 1) == 0) {
                   +  - ]
     427         [ #  # ]:          4 :                         SPDK_ERRLOG("Failed to populate '%s' iobuf large buffer cache at %d/%d entries. "
     428                 :            :                                     "You may need to increase spdk_iobuf_opts.large_pool_count (%"PRIu64")\n",
     429                 :            :                                     name, i, large_cache_size, g_iobuf.opts.large_pool_count);
     430                 :          4 :                         SPDK_ERRLOG("See scripts/calc-iobuf.py for guidance on how to calculate "
     431                 :            :                                     "this value.\n");
     432                 :          4 :                         return -ENOMEM;
     433                 :            :                 }
     434   [ +  -  +  -  :     404027 :                 STAILQ_INSERT_TAIL(&cache->large.cache, buf, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     435   [ +  -  +  - ]:     404027 :                 cache->large.cache_count++;
     436                 :      14601 :         }
     437                 :            : 
     438                 :      22981 :         return 0;
     439                 :        865 : }
     440                 :            : 
     441                 :            : int
     442                 :      22993 : spdk_iobuf_channel_init(struct spdk_iobuf_channel *ch, const char *name,
     443                 :            :                         uint32_t small_cache_size, uint32_t large_cache_size)
     444                 :            : {
     445                 :            :         struct spdk_io_channel *ioch;
     446                 :            :         struct iobuf_channel *iobuf_ch;
     447                 :            :         struct iobuf_module *module;
     448                 :            :         uint32_t i;
     449                 :            :         int32_t numa_id;
     450                 :            :         int rc;
     451                 :            : 
     452   [ +  +  +  -  :      37272 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          -  +  +  -  +  
                -  +  - ]
     453   [ +  +  +  +  :      37272 :                 if (strcmp(name, module->name) == 0) {
          +  +  +  -  +  
                      + ]
     454                 :      22993 :                         break;
     455                 :            :                 }
     456                 :        447 :         }
     457                 :            : 
     458         [ +  + ]:      22993 :         if (module == NULL) {
     459                 :          0 :                 SPDK_ERRLOG("Couldn't find iobuf module: '%s'\n", name);
     460                 :          0 :                 return -ENODEV;
     461                 :            :         }
     462                 :            : 
     463                 :      22993 :         ioch = spdk_get_io_channel(&g_iobuf);
     464         [ +  + ]:      22993 :         if (ioch == NULL) {
     465                 :          0 :                 SPDK_ERRLOG("Couldn't get iobuf IO channel\n");
     466                 :          0 :                 return -ENOMEM;
     467                 :            :         }
     468                 :            : 
     469                 :      22993 :         iobuf_ch = spdk_io_channel_get_ctx(ioch);
     470                 :            : 
     471         [ +  + ]:      45035 :         for (i = 0; i < IOBUF_MAX_CHANNELS; ++i) {
     472   [ +  +  +  -  :      45035 :                 if (iobuf_ch->channels[i] == NULL) {
             +  -  +  + ]
     473   [ +  -  +  -  :      22993 :                         iobuf_ch->channels[i] = ch;
                   +  - ]
     474                 :      22993 :                         break;
     475                 :            :                 }
     476                 :        443 :         }
     477                 :            : 
     478         [ -  + ]:      22993 :         if (i == IOBUF_MAX_CHANNELS) {
     479                 :          0 :                 SPDK_ERRLOG("Max number of iobuf channels (%" PRIu32 ") exceeded.\n", i);
     480                 :          0 :                 rc = -ENOMEM;
     481                 :          0 :                 goto error;
     482                 :            :         }
     483                 :            : 
     484   [ +  -  +  - ]:      22993 :         ch->parent = ioch;
     485   [ +  -  +  - ]:      22993 :         ch->module = module;
     486                 :            : 
     487   [ +  +  +  +  :      45986 :         IOBUF_FOREACH_NUMA_ID(numa_id) {
          +  +  +  -  -  
                      + ]
     488                 :      23858 :                 iobuf_channel_node_init(ch, iobuf_ch, numa_id,
     489                 :        865 :                                         small_cache_size, large_cache_size);
     490                 :        865 :         }
     491                 :            : 
     492   [ +  +  +  +  :      45974 :         IOBUF_FOREACH_NUMA_ID(numa_id) {
          +  +  +  -  -  
                      + ]
     493                 :      22993 :                 rc = iobuf_channel_node_populate(ch, name, numa_id);
     494         [ +  + ]:      22993 :                 if (rc) {
     495                 :         12 :                         goto error;
     496                 :            :                 }
     497                 :        862 :         }
     498                 :            : 
     499                 :      22981 :         return 0;
     500                 :          9 : error:
     501                 :         12 :         spdk_iobuf_channel_fini(ch);
     502                 :            : 
     503                 :         12 :         return rc;
     504                 :        865 : }
     505                 :            : 
     506                 :            : static void
     507                 :      22993 : iobuf_channel_node_fini(struct spdk_iobuf_channel *ch, int32_t numa_id)
     508                 :            : {
     509   [ +  -  +  - ]:      22993 :         struct spdk_iobuf_node_cache *cache = &ch->cache[numa_id];
     510         [ +  - ]:      22993 :         struct iobuf_node *node = &g_iobuf.node[numa_id];
     511                 :            :         struct spdk_iobuf_entry *entry __attribute__((unused));
     512                 :       5922 :         struct spdk_iobuf_buffer *buf;
     513                 :            : 
     514                 :            :         /* Make sure none of the wait queue entries are coming from this module */
     515   [ +  +  +  -  :      22993 :         STAILQ_FOREACH(entry, cache->small.queue, stailq) {
          +  -  +  -  +  
          -  -  +  #  #  
             #  #  #  # ]
     516   [ #  #  #  #  :          0 :                 assert(entry->module != ch->module);
          #  #  #  #  #  
                #  #  # ]
     517                 :          0 :         }
     518   [ +  +  +  -  :      22993 :         STAILQ_FOREACH(entry, cache->large.queue, stailq) {
          +  -  +  -  +  
          -  -  +  #  #  
             #  #  #  # ]
     519   [ #  #  #  #  :          0 :                 assert(entry->module != ch->module);
          #  #  #  #  #  
                #  #  # ]
     520                 :          0 :         }
     521                 :            : 
     522                 :            :         /* Release cached buffers back to the pool */
     523   [ +  +  +  -  :    3019200 :         while (!STAILQ_EMPTY(&cache->small.cache)) {
          +  -  +  -  +  
                      + ]
     524   [ +  -  +  -  :    2996207 :                 buf = STAILQ_FIRST(&cache->small.cache);
             +  -  +  - ]
     525   [ +  +  +  -  :    2996207 :                 STAILQ_REMOVE_HEAD(&cache->small.cache, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  +  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     526   [ +  -  +  - ]:    2996207 :                 spdk_ring_enqueue(node->small_pool, (void **)&buf, 1, NULL);
     527   [ +  -  +  - ]:    2996207 :                 cache->small.cache_count--;
     528                 :            :         }
     529   [ +  +  +  -  :     427053 :         while (!STAILQ_EMPTY(&cache->large.cache)) {
          +  -  +  -  +  
                      + ]
     530   [ +  -  +  -  :     404060 :                 buf = STAILQ_FIRST(&cache->large.cache);
             +  -  +  - ]
     531   [ +  +  +  -  :     404060 :                 STAILQ_REMOVE_HEAD(&cache->large.cache, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  +  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     532   [ +  -  +  - ]:     404060 :                 spdk_ring_enqueue(node->large_pool, (void **)&buf, 1, NULL);
     533   [ +  -  +  - ]:     404060 :                 cache->large.cache_count--;
     534                 :            :         }
     535                 :            : 
     536   [ +  +  +  -  :      22993 :         assert(cache->small.cache_count == 0);
          +  -  +  -  #  
                      # ]
     537   [ +  +  +  -  :      22993 :         assert(cache->large.cache_count == 0);
          +  -  +  -  #  
                      # ]
     538                 :      22993 : }
     539                 :            : 
     540                 :            : void
     541                 :      22993 : spdk_iobuf_channel_fini(struct spdk_iobuf_channel *ch)
     542                 :            : {
     543                 :            :         struct iobuf_channel *iobuf_ch;
     544                 :            :         uint32_t i;
     545                 :            : 
     546   [ +  +  +  +  :      45986 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  +  -  -  
                      + ]
     547                 :      22993 :                 iobuf_channel_node_fini(ch, i);
     548                 :        865 :         }
     549                 :            : 
     550   [ +  -  +  - ]:      22993 :         iobuf_ch = spdk_io_channel_get_ctx(ch->parent);
     551         [ +  + ]:      45035 :         for (i = 0; i < IOBUF_MAX_CHANNELS; ++i) {
     552   [ +  +  +  -  :      45035 :                 if (iobuf_ch->channels[i] == ch) {
             +  -  +  + ]
     553   [ +  -  +  -  :      22993 :                         iobuf_ch->channels[i] = NULL;
                   +  - ]
     554                 :      22993 :                         break;
     555                 :            :                 }
     556                 :        443 :         }
     557                 :            : 
     558   [ +  -  +  - ]:      22993 :         spdk_put_io_channel(ch->parent);
     559   [ +  -  +  - ]:      22993 :         ch->parent = NULL;
     560                 :      22993 : }
     561                 :            : 
     562                 :            : int
     563                 :       4816 : spdk_iobuf_register_module(const char *name)
     564                 :            : {
     565                 :            :         struct iobuf_module *module;
     566                 :            : 
     567   [ +  +  +  -  :       7546 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          +  +  +  -  +  
                -  +  - ]
     568   [ +  +  +  +  :       2731 :                 if (strcmp(name, module->name) == 0) {
          +  +  +  -  +  
                      - ]
     569                 :          1 :                         return -EEXIST;
     570                 :            :                 }
     571                 :        170 :         }
     572                 :            : 
     573                 :       4815 :         module = calloc(1, sizeof(*module));
     574         [ +  + ]:       4815 :         if (module == NULL) {
     575                 :          0 :                 return -ENOMEM;
     576                 :            :         }
     577                 :            : 
     578   [ +  +  +  -  :       4815 :         module->name = strdup(name);
                   +  - ]
     579   [ +  +  +  -  :       4815 :         if (module->name == NULL) {
                   +  - ]
     580                 :          0 :                 free(module);
     581                 :          0 :                 return -ENOMEM;
     582                 :            :         }
     583                 :            : 
     584   [ +  -  +  -  :       4815 :         TAILQ_INSERT_TAIL(&g_iobuf.modules, module, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     585                 :            : 
     586                 :       4815 :         return 0;
     587                 :        301 : }
     588                 :            : 
     589                 :            : int
     590                 :        328 : spdk_iobuf_unregister_module(const char *name)
     591                 :            : {
     592                 :            :         struct iobuf_module *module;
     593                 :            : 
     594   [ +  -  +  -  :        984 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          +  -  +  -  +  
                -  +  - ]
     595   [ +  +  +  +  :        984 :                 if (strcmp(name, module->name) == 0) {
          +  +  +  -  +  
                      + ]
     596   [ +  +  +  -  :        328 :                         TAILQ_REMOVE(&g_iobuf.modules, module, tailq);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  -  +  -  
          +  -  +  -  +  
          -  +  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     597   [ +  -  +  - ]:        328 :                         free(module->name);
     598                 :        328 :                         free(module);
     599                 :        328 :                         return 0;
     600                 :            :                 }
     601                 :         72 :         }
     602                 :            : 
     603                 :          0 :         return -ENOENT;
     604                 :         36 : }
     605                 :            : 
     606                 :            : static int
     607                 :     184600 : iobuf_pool_for_each_entry(struct spdk_iobuf_channel *ch, struct spdk_iobuf_pool_cache *pool,
     608                 :            :                           spdk_iobuf_for_each_entry_fn cb_fn, void *cb_ctx)
     609                 :            : {
     610                 :            :         struct spdk_iobuf_entry *entry, *tmp;
     611                 :            :         int rc;
     612                 :            : 
     613   [ +  +  +  +  :     184664 :         STAILQ_FOREACH_SAFE(entry, pool->queue, stailq, tmp) {
          +  -  +  -  +  
          -  #  #  #  #  
             #  #  -  + ]
     614                 :            :                 /* We only want to iterate over the entries requested by the module which owns ch */
     615   [ +  +  #  #  :         64 :                 if (entry->module != ch->module) {
          #  #  #  #  #  
                      # ]
     616                 :         32 :                         continue;
     617                 :            :                 }
     618                 :            : 
     619   [ #  #  #  # ]:         32 :                 rc = cb_fn(ch, entry, cb_ctx);
     620         [ -  + ]:         32 :                 if (rc != 0) {
     621                 :          0 :                         return rc;
     622                 :            :                 }
     623                 :          8 :         }
     624                 :            : 
     625                 :     184600 :         return 0;
     626                 :       1782 : }
     627                 :            : 
     628                 :            : int
     629                 :      92300 : spdk_iobuf_for_each_entry(struct spdk_iobuf_channel *ch,
     630                 :            :                           spdk_iobuf_for_each_entry_fn cb_fn, void *cb_ctx)
     631                 :            : {
     632                 :            :         struct spdk_iobuf_node_cache *cache;
     633                 :            :         uint32_t i;
     634                 :            :         int rc;
     635                 :            : 
     636   [ +  +  +  +  :     184600 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  +  -  +  
                      - ]
     637   [ +  -  +  - ]:      92300 :                 cache = &ch->cache[i];
     638                 :            : 
     639         [ +  - ]:      92300 :                 rc = iobuf_pool_for_each_entry(ch, &cache->small, cb_fn, cb_ctx);
     640         [ +  + ]:      92300 :                 if (rc != 0) {
     641                 :          0 :                         return rc;
     642                 :            :                 }
     643         [ +  - ]:      92300 :                 rc = iobuf_pool_for_each_entry(ch, &cache->large, cb_fn, cb_ctx);
     644         [ +  + ]:      92300 :                 if (rc != 0) {
     645                 :          0 :                         return rc;
     646                 :            :                 }
     647                 :        891 :         }
     648                 :            : 
     649                 :      92300 :         return 0;
     650                 :        891 : }
     651                 :            : 
     652                 :            : static bool
     653                 :         48 : iobuf_entry_abort_node(struct spdk_iobuf_channel *ch, int32_t numa_id,
     654                 :            :                        struct spdk_iobuf_entry *entry, uint64_t len)
     655                 :            : {
     656                 :            :         struct spdk_iobuf_node_cache *cache;
     657                 :            :         struct spdk_iobuf_pool_cache *pool;
     658                 :            :         struct spdk_iobuf_entry *e;
     659                 :            : 
     660   [ #  #  #  # ]:         48 :         cache = &ch->cache[numa_id];
     661                 :            : 
     662   [ +  +  #  #  :         48 :         if (len <= cache->small.bufsize) {
             #  #  #  # ]
     663         [ #  # ]:         24 :                 pool = &cache->small;
     664                 :          6 :         } else {
     665   [ +  +  #  #  :         24 :                 assert(len <= cache->large.bufsize);
          #  #  #  #  #  
                      # ]
     666         [ #  # ]:         24 :                 pool = &cache->large;
     667                 :            :         }
     668                 :            : 
     669   [ +  -  #  #  :         48 :         STAILQ_FOREACH(e, pool->queue, stailq) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     670         [ +  + ]:         48 :                 if (e == entry) {
     671   [ +  +  +  +  :         48 :                         STAILQ_REMOVE(pool->queue, entry, spdk_iobuf_entry, stailq);
          -  -  -  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     672                 :         48 :                         return true;
     673                 :            :                 }
     674                 :          0 :         }
     675                 :            : 
     676                 :          0 :         return false;
     677                 :         12 : }
     678                 :            : 
     679                 :            : void
     680                 :         48 : spdk_iobuf_entry_abort(struct spdk_iobuf_channel *ch, struct spdk_iobuf_entry *entry,
     681                 :            :                        uint64_t len)
     682                 :            : {
     683                 :            :         uint32_t i;
     684                 :            : 
     685   [ +  +  +  +  :         96 :         IOBUF_FOREACH_NUMA_ID(i) {
          +  +  #  #  #  
                      # ]
     686                 :         48 :                 iobuf_entry_abort_node(ch, i, entry, len);
     687                 :         12 :         }
     688                 :         48 : }
     689                 :            : 
     690                 :            : #define IOBUF_BATCH_SIZE 32
     691                 :            : 
     692                 :            : void *
     693                 :   40197733 : spdk_iobuf_get(struct spdk_iobuf_channel *ch, uint64_t len,
     694                 :            :                struct spdk_iobuf_entry *entry, spdk_iobuf_get_cb cb_fn)
     695                 :            : {
     696                 :            :         struct spdk_iobuf_node_cache *cache;
     697                 :            :         struct spdk_iobuf_pool_cache *pool;
     698                 :            :         void *buf;
     699                 :            : 
     700   [ +  -  +  - ]:   40197733 :         cache = &ch->cache[0];
     701                 :            : 
     702   [ +  +  +  -  :   40197733 :         assert(spdk_io_channel_get_thread(ch->parent) == spdk_get_thread());
             +  -  #  # ]
     703   [ +  +  +  -  :   40197733 :         if (len <= cache->small.bufsize) {
             +  -  +  - ]
     704         [ +  - ]:   39072369 :                 pool = &cache->small;
     705                 :    2153234 :         } else {
     706   [ -  +  #  #  :    1125364 :                 assert(len <= cache->large.bufsize);
          #  #  #  #  #  
                      # ]
     707         [ #  # ]:    1125364 :                 pool = &cache->large;
     708                 :            :         }
     709                 :            : 
     710   [ +  -  +  -  :   40197733 :         buf = (void *)STAILQ_FIRST(&pool->cache);
                   +  - ]
     711         [ +  + ]:   40197733 :         if (buf) {
     712   [ +  +  +  -  :   39413046 :                 STAILQ_REMOVE_HEAD(&pool->cache, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  -  
          +  #  #  #  #  
          #  #  #  #  #  
                      # ]
     713   [ +  +  +  -  :   39413046 :                 assert(pool->cache_count > 0);
             +  -  #  # ]
     714         [ +  - ]:   39413046 :                 pool->cache_count--;
     715   [ +  -  +  - ]:   39413046 :                 pool->stats.cache++;
     716                 :    2232006 :         } else {
     717                 :      40187 :                 struct spdk_iobuf_buffer *bufs[IOBUF_BATCH_SIZE];
     718                 :            :                 size_t sz, i;
     719                 :            : 
     720                 :            :                 /* If we're going to dequeue, we may as well dequeue a batch. */
     721   [ +  +  -  +  :     784687 :                 sz = spdk_ring_dequeue(pool->pool, (void **)bufs, spdk_min(IOBUF_BATCH_SIZE,
          +  +  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     722                 :            :                                        spdk_max(pool->cache_size, 1)));
     723         [ +  + ]:     784687 :                 if (sz == 0) {
     724         [ +  + ]:     713952 :                         if (entry) {
     725   [ #  #  #  #  :      88714 :                                 STAILQ_INSERT_TAIL(pool->queue, entry, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     726   [ #  #  #  #  :      88714 :                                 entry->module = ch->module;
             #  #  #  # ]
     727   [ #  #  #  # ]:      88714 :                                 entry->cb_fn = cb_fn;
     728   [ #  #  #  # ]:      88714 :                                 pool->stats.retry++;
     729                 :      43748 :                         }
     730                 :            : 
     731                 :     713952 :                         return NULL;
     732                 :            :                 }
     733                 :            : 
     734   [ #  #  #  # ]:      70735 :                 pool->stats.main++;
     735         [ +  + ]:    2030545 :                 for (i = 0; i < (sz - 1); i++) {
     736   [ +  +  #  #  :    1959810 :                         STAILQ_INSERT_HEAD(&pool->cache, bufs[i], stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     737         [ #  # ]:    1959810 :                         pool->cache_count++;
     738                 :      26704 :                 }
     739                 :            : 
     740                 :            :                 /* The last one is the one we'll return */
     741   [ #  #  #  #  :      70735 :                 buf = bufs[i];
                   #  # ]
     742                 :            :         }
     743                 :            : 
     744                 :   39483781 :         return (char *)buf;
     745                 :    2277555 : }
     746                 :            : 
     747                 :            : void
     748                 :   39613008 : spdk_iobuf_put(struct spdk_iobuf_channel *ch, void *buf, uint64_t len)
     749                 :            : {
     750                 :            :         struct spdk_iobuf_entry *entry;
     751                 :            :         struct spdk_iobuf_buffer *iobuf_buf;
     752                 :            :         struct spdk_iobuf_node_cache *cache;
     753                 :            :         struct spdk_iobuf_pool_cache *pool;
     754                 :            :         uint32_t numa_id;
     755                 :            :         size_t sz;
     756                 :            : 
     757   [ +  +  -  + ]:   39613008 :         if (g_iobuf.opts.enable_numa) {
     758                 :       5971 :                 numa_id = spdk_mem_get_numa_id(buf, NULL);
     759                 :       5971 :         } else {
     760                 :   39607037 :                 numa_id = 0;
     761                 :            :         }
     762                 :            : 
     763   [ +  -  +  - ]:   39613008 :         cache = &ch->cache[numa_id];
     764                 :            : 
     765   [ +  +  +  -  :   39613008 :         assert(spdk_io_channel_get_thread(ch->parent) == spdk_get_thread());
             +  -  #  # ]
     766   [ +  +  +  -  :   39601066 :         if (len <= cache->small.bufsize) {
             +  -  +  - ]
     767         [ +  - ]:   38475748 :                 pool = &cache->small;
     768                 :    2181965 :         } else {
     769         [ #  # ]:    1125318 :                 pool = &cache->large;
     770                 :            :         }
     771                 :            : 
     772   [ +  +  +  -  :   39601066 :         if (STAILQ_EMPTY(pool->queue)) {
          +  -  +  -  -  
                      + ]
     773   [ +  +  +  -  :   39512394 :                 if (pool->cache_size == 0) {
                   +  - ]
     774   [ #  #  #  # ]:         72 :                         spdk_ring_enqueue(pool->pool, (void **)&buf, 1, NULL);
     775                 :         72 :                         return;
     776                 :            :                 }
     777                 :            : 
     778                 :   39512322 :                 iobuf_buf = (struct spdk_iobuf_buffer *)buf;
     779                 :            : 
     780   [ +  +  +  -  :   39512322 :                 STAILQ_INSERT_HEAD(&pool->cache, iobuf_buf, stailq);
          +  -  +  -  +  
          -  +  -  +  -  
          #  #  #  #  #  
          #  #  #  #  #  
          +  -  +  -  +  
                      - ]
     781         [ +  - ]:   39512322 :                 pool->cache_count++;
     782                 :            : 
     783                 :            :                 /* The cache size may exceed the configured amount. We always dequeue from the
     784                 :            :                  * central pool in batches of known size, so wait until at least a batch
     785                 :            :                  * has been returned to actually return the buffers to the central pool. */
     786   [ +  +  +  -  :   39512322 :                 sz = spdk_min(IOBUF_BATCH_SIZE, pool->cache_size);
          -  +  +  -  +  
                      - ]
     787   [ +  +  +  -  :   39512322 :                 if (pool->cache_count >= pool->cache_size + sz) {
          +  -  +  -  +  
                      - ]
     788                 :       8289 :                         struct spdk_iobuf_buffer *bufs[IOBUF_BATCH_SIZE];
     789                 :            :                         size_t i;
     790                 :            : 
     791         [ +  + ]:    2101054 :                         for (i = 0; i < sz; i++) {
     792   [ #  #  #  #  :    2030400 :                                 bufs[i] = STAILQ_FIRST(&pool->cache);
          #  #  #  #  #  
                #  #  # ]
     793   [ +  +  #  #  :    2030400 :                                 STAILQ_REMOVE_HEAD(&pool->cache, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     794   [ +  +  #  #  :    2030400 :                                 assert(pool->cache_count > 0);
             #  #  #  # ]
     795         [ #  # ]:    2030400 :                                 pool->cache_count--;
     796                 :      28484 :                         }
     797                 :            : 
     798   [ #  #  #  # ]:      70654 :                         spdk_ring_enqueue(pool->pool, (void **)bufs, sz, NULL);
     799                 :       1783 :                 }
     800                 :    2262528 :         } else {
     801   [ #  #  #  #  :      88672 :                 entry = STAILQ_FIRST(pool->queue);
             #  #  #  # ]
     802   [ +  +  #  #  :      88672 :                 STAILQ_REMOVE_HEAD(pool->queue, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     803   [ #  #  #  #  :      88672 :                 entry->cb_fn(entry, buf);
             #  #  #  # ]
     804   [ +  +  +  +  :      88672 :                 if (spdk_unlikely(entry == STAILQ_LAST(pool->queue, spdk_iobuf_entry, stailq))) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     805   [ +  +  +  +  :      13370 :                         STAILQ_REMOVE(pool->queue, entry, spdk_iobuf_entry, stailq);
          +  +  +  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     806   [ +  +  #  #  :       7055 :                         STAILQ_INSERT_HEAD(pool->queue, entry, stailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     807                 :          2 :                 }
     808                 :            :         }
     809                 :    2306288 : }
     810                 :            : 
     811                 :            : static void
     812                 :          3 : iobuf_get_channel_stats_done(struct spdk_io_channel_iter *iter, int status)
     813                 :            : {
     814                 :          3 :         struct iobuf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(iter);
     815                 :            : 
     816   [ #  #  #  #  :          3 :         ctx->cb_fn(ctx->modules, ctx->num_modules, ctx->cb_arg);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     817   [ #  #  #  # ]:          3 :         free(ctx->modules);
     818                 :          3 :         free(ctx);
     819                 :          3 : }
     820                 :            : 
     821                 :            : static void
     822                 :          3 : iobuf_get_channel_stats(struct spdk_io_channel_iter *iter)
     823                 :            : {
     824                 :          3 :         struct iobuf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(iter);
     825                 :          3 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(iter);
     826                 :          3 :         struct iobuf_channel *iobuf_ch = spdk_io_channel_get_ctx(ch);
     827                 :            :         struct spdk_iobuf_channel *channel;
     828                 :            :         struct iobuf_module *module;
     829                 :            :         struct spdk_iobuf_module_stats *it;
     830                 :            :         uint32_t i, j;
     831                 :            : 
     832   [ +  +  #  #  :         12 :         for (i = 0; i < ctx->num_modules; ++i) {
                   #  # ]
     833         [ +  - ]:         18 :                 for (j = 0; j < IOBUF_MAX_CHANNELS; ++j) {
     834   [ #  #  #  #  :         18 :                         channel = iobuf_ch->channels[j];
                   #  # ]
     835         [ -  + ]:         18 :                         if (channel == NULL) {
     836                 :          0 :                                 continue;
     837                 :            :                         }
     838                 :            : 
     839   [ #  #  #  #  :         18 :                         it = &ctx->modules[i];
                   #  # ]
     840   [ #  #  #  # ]:         18 :                         module = (struct iobuf_module *)channel->module;
     841   [ -  +  -  +  :         18 :                         if (strcmp(it->module, module->name) == 0) {
          +  +  #  #  #  
             #  #  #  #  
                      # ]
     842                 :            :                                 struct spdk_iobuf_pool_cache *cache;
     843                 :            :                                 uint32_t i;
     844                 :            : 
     845   [ -  +  +  +  :         18 :                                 IOBUF_FOREACH_NUMA_ID(i) {
          #  #  #  #  #  
                      # ]
     846   [ #  #  #  #  :          9 :                                         cache = &channel->cache[i].small;
                   #  # ]
     847   [ #  #  #  #  :          9 :                                         it->small_pool.cache += cache->stats.cache;
          #  #  #  #  #  
                #  #  # ]
     848   [ #  #  #  #  :          9 :                                         it->small_pool.main += cache->stats.main;
          #  #  #  #  #  
                #  #  # ]
     849   [ #  #  #  #  :          9 :                                         it->small_pool.retry += cache->stats.retry;
          #  #  #  #  #  
                #  #  # ]
     850                 :            : 
     851   [ #  #  #  #  :          9 :                                         cache = &channel->cache[i].large;
                   #  # ]
     852   [ #  #  #  #  :          9 :                                         it->large_pool.cache += cache->stats.cache;
          #  #  #  #  #  
                #  #  # ]
     853   [ #  #  #  #  :          9 :                                         it->large_pool.main += cache->stats.main;
          #  #  #  #  #  
                #  #  # ]
     854   [ -  +  #  #  :          9 :                                         it->large_pool.retry += cache->stats.retry;
          #  #  #  #  #  
                #  #  # ]
     855                 :          0 :                                 }
     856                 :          9 :                                 break;
     857                 :            :                         }
     858                 :          0 :                 }
     859                 :          0 :         }
     860                 :            : 
     861                 :          3 :         spdk_for_each_channel_continue(iter, 0);
     862                 :          3 : }
     863                 :            : 
     864                 :            : int
     865                 :          3 : spdk_iobuf_get_stats(spdk_iobuf_get_stats_cb cb_fn, void *cb_arg)
     866                 :            : {
     867                 :            :         struct iobuf_module *module;
     868                 :            :         struct iobuf_get_stats_ctx *ctx;
     869                 :            :         uint32_t i;
     870                 :            : 
     871                 :          3 :         ctx = calloc(1, sizeof(*ctx));
     872         [ -  + ]:          3 :         if (ctx == NULL) {
     873                 :          0 :                 return -ENOMEM;
     874                 :            :         }
     875                 :            : 
     876   [ +  +  #  #  :         12 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          #  #  #  #  #  
                #  #  # ]
     877         [ #  # ]:          9 :                 ++ctx->num_modules;
     878                 :          0 :         }
     879                 :            : 
     880   [ #  #  #  #  :          3 :         ctx->modules = calloc(ctx->num_modules, sizeof(struct spdk_iobuf_module_stats));
             #  #  #  # ]
     881   [ -  +  #  #  :          3 :         if (ctx->modules == NULL) {
                   #  # ]
     882                 :          0 :                 free(ctx);
     883                 :          0 :                 return -ENOMEM;
     884                 :            :         }
     885                 :            : 
     886                 :          3 :         i = 0;
     887   [ +  +  #  #  :         12 :         TAILQ_FOREACH(module, &g_iobuf.modules, tailq) {
          #  #  #  #  #  
                #  #  # ]
     888   [ #  #  #  #  :          9 :                 ctx->modules[i].module = module->name;
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     889                 :          9 :                 ++i;
     890                 :          0 :         }
     891                 :            : 
     892   [ #  #  #  # ]:          3 :         ctx->cb_fn = cb_fn;
     893   [ #  #  #  # ]:          3 :         ctx->cb_arg = cb_arg;
     894                 :            : 
     895                 :          3 :         spdk_for_each_channel(&g_iobuf, iobuf_get_channel_stats, ctx,
     896                 :            :                               iobuf_get_channel_stats_done);
     897                 :          3 :         return 0;
     898                 :          0 : }

Generated by: LCOV version 1.15