LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/thread/iobuf.c - iobuf_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 451 451 100.0 %
Date: 2024-08-10 23:32:34 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 16 16 100.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2023 Intel Corporation. All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "spdk_internal/cunit.h"
       6                 :            : 
       7                 :            : #include "common/lib/ut_multithread.c"
       8                 :            : #include "unit/lib/json_mock.c"
       9                 :            : 
      10                 :            : #include "spdk/config.h"
      11                 :            : #include "spdk/thread.h"
      12                 :            : 
      13                 :            : #include "thread/iobuf.c"
      14                 :            : 
      15                 :            : struct ut_iobuf_entry {
      16                 :            :         struct spdk_iobuf_channel       *ioch;
      17                 :            :         struct spdk_iobuf_entry         iobuf;
      18                 :            :         void                            *buf;
      19                 :            :         void                            *buf2;
      20                 :            :         uint32_t                        thread_id;
      21                 :            :         const char                      *module;
      22                 :            : };
      23                 :            : 
      24                 :            : static void
      25                 :         15 : ut_iobuf_finish_cb(void *ctx)
      26                 :            : {
      27                 :         15 :         *(int *)ctx = 1;
      28                 :         15 : }
      29                 :            : 
      30                 :            : static void
      31                 :         60 : ut_iobuf_get_buf_cb(struct spdk_iobuf_entry *entry, void *buf)
      32                 :            : {
      33                 :         60 :         struct ut_iobuf_entry *ut_entry = SPDK_CONTAINEROF(entry, struct ut_iobuf_entry, iobuf);
      34                 :            : 
      35                 :         60 :         ut_entry->buf = buf;
      36                 :         60 : }
      37                 :            : 
      38                 :            : static int
      39                 :         40 : ut_iobuf_foreach_cb(struct spdk_iobuf_channel *ch, struct spdk_iobuf_entry *entry, void *cb_arg)
      40                 :            : {
      41                 :         40 :         struct ut_iobuf_entry *ut_entry = SPDK_CONTAINEROF(entry, struct ut_iobuf_entry, iobuf);
      42                 :            : 
      43                 :         40 :         ut_entry->buf = cb_arg;
      44                 :            : 
      45                 :         40 :         return 0;
      46                 :            : }
      47                 :            : 
      48                 :            : #define SMALL_BUFSIZE 4096
      49                 :            : #define LARGE_BUFSIZE 8192
      50                 :            : 
      51                 :            : static void
      52                 :          5 : iobuf(void)
      53                 :            : {
      54                 :          5 :         struct spdk_iobuf_opts opts = {
      55                 :            :                 .small_pool_count = 2,
      56                 :            :                 .large_pool_count = 2,
      57                 :            :                 .small_bufsize = SMALL_BUFSIZE,
      58                 :            :                 .large_bufsize = LARGE_BUFSIZE,
      59                 :            :         };
      60                 :            :         struct ut_iobuf_entry *entry;
      61                 :          4 :         struct spdk_iobuf_channel mod0_ch[2], mod1_ch[2];
      62                 :          5 :         struct ut_iobuf_entry mod0_entries[] = {
      63                 :            :                 { .thread_id = 0, .module = "ut_module0", },
      64                 :            :                 { .thread_id = 0, .module = "ut_module0", },
      65                 :            :                 { .thread_id = 0, .module = "ut_module0", },
      66                 :            :                 { .thread_id = 0, .module = "ut_module0", },
      67                 :            :                 { .thread_id = 1, .module = "ut_module0", },
      68                 :            :                 { .thread_id = 1, .module = "ut_module0", },
      69                 :            :                 { .thread_id = 1, .module = "ut_module0", },
      70                 :            :                 { .thread_id = 1, .module = "ut_module0", },
      71                 :            :         };
      72                 :          5 :         struct ut_iobuf_entry mod1_entries[] = {
      73                 :            :                 { .thread_id = 0, .module = "ut_module1", },
      74                 :            :                 { .thread_id = 0, .module = "ut_module1", },
      75                 :            :                 { .thread_id = 0, .module = "ut_module1", },
      76                 :            :                 { .thread_id = 0, .module = "ut_module1", },
      77                 :            :                 { .thread_id = 1, .module = "ut_module1", },
      78                 :            :                 { .thread_id = 1, .module = "ut_module1", },
      79                 :            :                 { .thread_id = 1, .module = "ut_module1", },
      80                 :            :                 { .thread_id = 1, .module = "ut_module1", },
      81                 :            :         };
      82                 :          5 :         int rc, finish = 0;
      83                 :            :         uint32_t i;
      84                 :            : 
      85                 :          5 :         allocate_cores(2);
      86                 :          5 :         allocate_threads(2);
      87                 :            : 
      88                 :          5 :         set_thread(0);
      89                 :            : 
      90                 :            :         /* We cannot use spdk_iobuf_set_opts(), as it won't allow us to use such small pools */
      91                 :          5 :         g_iobuf.opts = opts;
      92                 :          5 :         rc = spdk_iobuf_initialize();
      93                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
      94                 :            : 
      95                 :          5 :         rc = spdk_iobuf_register_module("ut_module0");
      96                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
      97                 :            : 
      98                 :          5 :         rc = spdk_iobuf_register_module("ut_module1");
      99                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     100                 :            : 
     101                 :          5 :         set_thread(0);
     102                 :          5 :         rc = spdk_iobuf_channel_init(&mod0_ch[0], "ut_module0", 0, 0);
     103                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     104                 :          5 :         set_thread(1);
     105                 :          5 :         rc = spdk_iobuf_channel_init(&mod0_ch[1], "ut_module0", 0, 0);
     106                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     107         [ +  + ]:         45 :         for (i = 0; i < SPDK_COUNTOF(mod0_entries); ++i) {
     108                 :         40 :                 mod0_entries[i].ioch = &mod0_ch[mod0_entries[i].thread_id];
     109                 :            :         }
     110                 :          5 :         set_thread(0);
     111                 :          5 :         rc = spdk_iobuf_channel_init(&mod1_ch[0], "ut_module1", 0, 0);
     112                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     113                 :          5 :         set_thread(1);
     114                 :          5 :         rc = spdk_iobuf_channel_init(&mod1_ch[1], "ut_module1", 0, 0);
     115                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     116         [ +  + ]:         45 :         for (i = 0; i < SPDK_COUNTOF(mod1_entries); ++i) {
     117                 :         40 :                 mod1_entries[i].ioch = &mod1_ch[mod1_entries[i].thread_id];
     118                 :            :         }
     119                 :            : 
     120                 :            :         /* First check that it's possible to retrieve the whole pools from a single module */
     121                 :          5 :         set_thread(0);
     122                 :          5 :         entry = &mod0_entries[0];
     123                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     124                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     125                 :          5 :         entry = &mod0_entries[1];
     126                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     127                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     128                 :            :         /* The next two should be put onto the large buf wait queue */
     129                 :          5 :         entry = &mod0_entries[2];
     130                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     131                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     132                 :          5 :         entry = &mod0_entries[3];
     133                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     134                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     135                 :            :         /* Pick the two next buffers from the small pool */
     136                 :          5 :         set_thread(1);
     137                 :          5 :         entry = &mod0_entries[4];
     138                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     139                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     140                 :          5 :         entry = &mod0_entries[5];
     141                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     142                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     143                 :            :         /* The next two should be put onto the small buf wait queue */
     144                 :          5 :         entry = &mod0_entries[6];
     145                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     146                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     147                 :          5 :         entry = &mod0_entries[7];
     148                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     149                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     150                 :            : 
     151                 :            :         /* Now return one of the large buffers to the pool and verify that the first request's
     152                 :            :          * (entry 2) callback was executed and it was removed from the wait queue.
     153                 :            :          */
     154                 :          5 :         set_thread(0);
     155                 :          5 :         entry = &mod0_entries[0];
     156                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     157                 :          5 :         entry = &mod0_entries[2];
     158                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     159                 :          5 :         entry = &mod0_entries[3];
     160                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     161                 :            : 
     162                 :            :         /* Return the second buffer and check that the other request is satisfied */
     163                 :          5 :         entry = &mod0_entries[1];
     164                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     165                 :          5 :         entry = &mod0_entries[3];
     166                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     167                 :            : 
     168                 :            :         /* Return the remaining two buffers */
     169                 :          5 :         entry = &mod0_entries[2];
     170                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     171                 :          5 :         entry = &mod0_entries[3];
     172                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     173                 :            : 
     174                 :            :         /* Check that it didn't change the requests waiting for the small buffers */
     175                 :          5 :         entry = &mod0_entries[6];
     176                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     177                 :          5 :         entry = &mod0_entries[7];
     178                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     179                 :            : 
     180                 :            :         /* Do the same test as above, this time using the small pool */
     181                 :          5 :         set_thread(1);
     182                 :          5 :         entry = &mod0_entries[4];
     183                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     184                 :          5 :         entry = &mod0_entries[6];
     185                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     186                 :          5 :         entry = &mod0_entries[7];
     187                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     188                 :            : 
     189                 :            :         /* Return the second buffer and check that the other request is satisfied */
     190                 :          5 :         entry = &mod0_entries[5];
     191                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     192                 :          5 :         entry = &mod0_entries[7];
     193                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     194                 :            : 
     195                 :            :         /* Return the remaining two buffers */
     196                 :          5 :         entry = &mod0_entries[6];
     197                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     198                 :          5 :         entry = &mod0_entries[7];
     199                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     200                 :            : 
     201                 :            :         /* Now check requesting buffers from different modules - first request all of them from one
     202                 :            :          * module, starting from the large pool
     203                 :            :          */
     204                 :          5 :         set_thread(0);
     205                 :          5 :         entry = &mod0_entries[0];
     206                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     207                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     208                 :          5 :         entry = &mod0_entries[1];
     209                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     210                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     211                 :            :         /* Request all of them from the small one */
     212                 :          5 :         set_thread(1);
     213                 :          5 :         entry = &mod0_entries[4];
     214                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     215                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     216                 :          5 :         entry = &mod0_entries[5];
     217                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     218                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     219                 :            : 
     220                 :            :         /* Request one buffer per module from each pool  */
     221                 :          5 :         set_thread(0);
     222                 :          5 :         entry = &mod1_entries[0];
     223                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     224                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     225                 :          5 :         entry = &mod0_entries[3];
     226                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     227                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     228                 :            :         /* Change the order from the small pool and request a buffer from mod0 first */
     229                 :          5 :         set_thread(1);
     230                 :          5 :         entry = &mod0_entries[6];
     231                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     232                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     233                 :          5 :         entry = &mod1_entries[4];
     234                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     235                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     236                 :            : 
     237                 :            :         /* Now return one buffer to the large pool */
     238                 :          5 :         set_thread(0);
     239                 :          5 :         entry = &mod0_entries[0];
     240                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     241                 :            : 
     242                 :            :         /* Make sure the request from mod1 got the buffer, as it was the first to request it */
     243                 :          5 :         entry = &mod1_entries[0];
     244                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     245                 :          5 :         entry = &mod0_entries[3];
     246                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     247                 :            : 
     248                 :            :         /* Return second buffer to the large pool and check the outstanding mod0 request */
     249                 :          5 :         entry = &mod0_entries[1];
     250                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     251                 :          5 :         entry = &mod0_entries[3];
     252                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     253                 :            : 
     254                 :            :         /* Return the remaining two buffers */
     255                 :          5 :         entry = &mod1_entries[0];
     256                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     257                 :          5 :         entry = &mod0_entries[3];
     258                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     259                 :            : 
     260                 :            :         /* Check the same for the small pool, but this time the order of the request is reversed
     261                 :            :          * (mod0 before mod1)
     262                 :            :          */
     263                 :          5 :         set_thread(1);
     264                 :          5 :         entry = &mod0_entries[4];
     265                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     266                 :          5 :         entry = &mod0_entries[6];
     267                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     268                 :            :         /* mod1 request was second in this case, so it still needs to wait */
     269                 :          5 :         entry = &mod1_entries[4];
     270                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     271                 :            : 
     272                 :            :         /* Return the second requested buffer */
     273                 :          5 :         entry = &mod0_entries[5];
     274                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     275                 :          5 :         entry = &mod1_entries[4];
     276                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     277                 :            : 
     278                 :            :         /* Return the remaining two buffers */
     279                 :          5 :         entry = &mod0_entries[6];
     280                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     281                 :          5 :         entry = &mod1_entries[4];
     282                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     283                 :            : 
     284                 :            :         /* Request buffers to make the pools empty */
     285                 :          5 :         set_thread(0);
     286                 :          5 :         entry = &mod0_entries[0];
     287                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     288                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     289                 :          5 :         entry = &mod1_entries[0];
     290                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     291                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     292                 :          5 :         entry = &mod0_entries[1];
     293                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     294                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     295                 :          5 :         entry = &mod1_entries[1];
     296                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     297                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     298                 :            : 
     299                 :            :         /* Queue more requests from both modules */
     300                 :          5 :         entry = &mod0_entries[2];
     301                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     302                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     303                 :          5 :         entry = &mod1_entries[2];
     304                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     305                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     306                 :          5 :         entry = &mod1_entries[3];
     307                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     308                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     309                 :          5 :         entry = &mod0_entries[3];
     310                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     311                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     312                 :            : 
     313                 :            :         /* Check that abort correctly remove an entry from the queue */
     314                 :          5 :         entry = &mod0_entries[2];
     315                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, LARGE_BUFSIZE);
     316                 :          5 :         entry = &mod1_entries[3];
     317                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, SMALL_BUFSIZE);
     318                 :            : 
     319                 :          5 :         entry = &mod0_entries[0];
     320                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     321                 :          5 :         CU_ASSERT_PTR_NOT_NULL(mod1_entries[2].buf);
     322                 :          5 :         entry = &mod0_entries[1];
     323                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     324                 :          5 :         CU_ASSERT_PTR_NOT_NULL(mod0_entries[3].buf);
     325                 :            : 
     326                 :            :         /* Clean up */
     327                 :          5 :         entry = &mod1_entries[0];
     328                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     329                 :          5 :         entry = &mod1_entries[2];
     330                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     331                 :          5 :         entry = &mod1_entries[1];
     332                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     333                 :          5 :         entry = &mod0_entries[3];
     334                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     335                 :            : 
     336                 :            :         /* Request buffers to make the pools empty */
     337                 :          5 :         set_thread(0);
     338                 :          5 :         entry = &mod0_entries[0];
     339                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     340                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     341                 :          5 :         entry = &mod1_entries[0];
     342                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     343                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     344                 :          5 :         entry = &mod0_entries[1];
     345                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     346                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     347                 :          5 :         entry = &mod1_entries[1];
     348                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     349                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     350                 :            : 
     351                 :            :         /* Request a buffer from each queue and each module on thread 0 */
     352                 :          5 :         set_thread(0);
     353                 :          5 :         entry = &mod0_entries[2];
     354                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     355                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     356                 :          5 :         entry = &mod1_entries[2];
     357                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     358                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     359                 :          5 :         entry = &mod0_entries[3];
     360                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     361                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     362                 :          5 :         entry = &mod1_entries[3];
     363                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     364                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     365                 :            : 
     366                 :            :         /* Do the same on thread 1 */
     367                 :          5 :         set_thread(1);
     368                 :          5 :         entry = &mod0_entries[6];
     369                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     370                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     371                 :          5 :         entry = &mod1_entries[6];
     372                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, LARGE_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     373                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     374                 :          5 :         entry = &mod0_entries[7];
     375                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     376                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     377                 :          5 :         entry = &mod1_entries[7];
     378                 :          5 :         entry->buf = spdk_iobuf_get(entry->ioch, SMALL_BUFSIZE, &entry->iobuf, ut_iobuf_get_buf_cb);
     379                 :          5 :         CU_ASSERT_PTR_NULL(entry->buf);
     380                 :            : 
     381                 :            :         /* Now do the foreach and check that correct entries are iterated over by assigning their
     382                 :            :          * ->buf pointers to different values.
     383                 :            :          */
     384                 :          5 :         set_thread(0);
     385                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod0_ch[0], &mod0_ch[0].large,
     386                 :            :                                        ut_iobuf_foreach_cb, (void *)0xdeadbeef);
     387                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     388                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod0_ch[0], &mod0_ch[0].small,
     389                 :            :                                        ut_iobuf_foreach_cb, (void *)0xbeefdead);
     390                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     391                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod1_ch[0], &mod1_ch[0].large,
     392                 :            :                                        ut_iobuf_foreach_cb, (void *)0xfeedbeef);
     393                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     394                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod1_ch[0], &mod1_ch[0].small,
     395                 :            :                                        ut_iobuf_foreach_cb, (void *)0xbeeffeed);
     396                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     397                 :          5 :         set_thread(1);
     398                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod0_ch[1], &mod0_ch[1].large,
     399                 :            :                                        ut_iobuf_foreach_cb, (void *)0xcafebabe);
     400                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     401                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod0_ch[1], &mod0_ch[1].small,
     402                 :            :                                        ut_iobuf_foreach_cb, (void *)0xbabecafe);
     403                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     404                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod1_ch[1], &mod1_ch[1].large,
     405                 :            :                                        ut_iobuf_foreach_cb, (void *)0xbeefcafe);
     406                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     407                 :          5 :         rc = spdk_iobuf_for_each_entry(&mod1_ch[1], &mod1_ch[1].small,
     408                 :            :                                        ut_iobuf_foreach_cb, (void *)0xcafebeef);
     409                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     410                 :            : 
     411                 :            :         /* thread 0 */
     412                 :          5 :         CU_ASSERT_PTR_EQUAL(mod0_entries[2].buf, (void *)0xdeadbeef);
     413                 :          5 :         CU_ASSERT_PTR_EQUAL(mod0_entries[3].buf, (void *)0xbeefdead);
     414                 :          5 :         CU_ASSERT_PTR_EQUAL(mod1_entries[2].buf, (void *)0xfeedbeef);
     415                 :          5 :         CU_ASSERT_PTR_EQUAL(mod1_entries[3].buf, (void *)0xbeeffeed);
     416                 :            :         /* thread 1 */
     417                 :          5 :         CU_ASSERT_PTR_EQUAL(mod0_entries[6].buf, (void *)0xcafebabe);
     418                 :          5 :         CU_ASSERT_PTR_EQUAL(mod0_entries[7].buf, (void *)0xbabecafe);
     419                 :          5 :         CU_ASSERT_PTR_EQUAL(mod1_entries[6].buf, (void *)0xbeefcafe);
     420                 :          5 :         CU_ASSERT_PTR_EQUAL(mod1_entries[7].buf, (void *)0xcafebeef);
     421                 :            : 
     422                 :            :         /* Clean everything up */
     423                 :          5 :         set_thread(0);
     424                 :          5 :         entry = &mod0_entries[2];
     425                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, LARGE_BUFSIZE);
     426                 :          5 :         entry = &mod0_entries[3];
     427                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, SMALL_BUFSIZE);
     428                 :          5 :         entry = &mod1_entries[2];
     429                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, LARGE_BUFSIZE);
     430                 :          5 :         entry = &mod1_entries[3];
     431                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, SMALL_BUFSIZE);
     432                 :            : 
     433                 :          5 :         entry = &mod0_entries[0];
     434                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     435                 :          5 :         entry = &mod1_entries[0];
     436                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, LARGE_BUFSIZE);
     437                 :          5 :         entry = &mod0_entries[1];
     438                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     439                 :          5 :         entry = &mod1_entries[1];
     440                 :          5 :         spdk_iobuf_put(entry->ioch, entry->buf, SMALL_BUFSIZE);
     441                 :            : 
     442                 :          5 :         set_thread(1);
     443                 :          5 :         entry = &mod0_entries[6];
     444                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, LARGE_BUFSIZE);
     445                 :          5 :         entry = &mod0_entries[7];
     446                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, SMALL_BUFSIZE);
     447                 :          5 :         entry = &mod1_entries[6];
     448                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, LARGE_BUFSIZE);
     449                 :          5 :         entry = &mod1_entries[7];
     450                 :          5 :         spdk_iobuf_entry_abort(entry->ioch, &entry->iobuf, SMALL_BUFSIZE);
     451                 :            : 
     452                 :          5 :         set_thread(0);
     453                 :          5 :         spdk_iobuf_channel_fini(&mod0_ch[0]);
     454                 :          5 :         poll_threads();
     455                 :          5 :         spdk_iobuf_channel_fini(&mod1_ch[0]);
     456                 :          5 :         poll_threads();
     457                 :          5 :         set_thread(1);
     458                 :          5 :         spdk_iobuf_channel_fini(&mod0_ch[1]);
     459                 :          5 :         poll_threads();
     460                 :          5 :         spdk_iobuf_channel_fini(&mod1_ch[1]);
     461                 :          5 :         poll_threads();
     462                 :            : 
     463                 :          5 :         spdk_iobuf_finish(ut_iobuf_finish_cb, &finish);
     464                 :          5 :         poll_threads();
     465                 :            : 
     466                 :          5 :         CU_ASSERT_EQUAL(finish, 1);
     467                 :            : 
     468                 :          5 :         free_threads();
     469                 :          5 :         free_cores();
     470                 :          5 : }
     471                 :            : 
     472                 :            : static void
     473                 :          5 : iobuf_cache(void)
     474                 :            : {
     475                 :          5 :         struct spdk_iobuf_opts opts = {
     476                 :            :                 .small_pool_count = 4,
     477                 :            :                 .large_pool_count = 4,
     478                 :            :                 .small_bufsize = SMALL_BUFSIZE,
     479                 :            :                 .large_bufsize = LARGE_BUFSIZE,
     480                 :            :         };
     481                 :          4 :         struct spdk_iobuf_channel iobuf_ch[2];
     482                 :            :         struct ut_iobuf_entry *entry;
     483                 :          5 :         struct ut_iobuf_entry mod0_entries[] = {
     484                 :            :                 { .thread_id = 0, .module = "ut_module0", },
     485                 :            :                 { .thread_id = 0, .module = "ut_module0", },
     486                 :            :                 { .thread_id = 0, .module = "ut_module0", },
     487                 :            :                 { .thread_id = 0, .module = "ut_module0", },
     488                 :            :         };
     489                 :          5 :         struct ut_iobuf_entry mod1_entries[] = {
     490                 :            :                 { .thread_id = 0, .module = "ut_module1", },
     491                 :            :                 { .thread_id = 0, .module = "ut_module1", },
     492                 :            :         };
     493                 :          5 :         int rc, finish = 0;
     494                 :            :         uint32_t i, j, bufsize;
     495                 :            : 
     496                 :          5 :         allocate_cores(1);
     497                 :          5 :         allocate_threads(1);
     498                 :            : 
     499                 :          5 :         set_thread(0);
     500                 :            : 
     501                 :            :         /* We cannot use spdk_iobuf_set_opts(), as it won't allow us to use such small pools */
     502                 :          5 :         g_iobuf.opts = opts;
     503                 :          5 :         rc = spdk_iobuf_initialize();
     504                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     505                 :            : 
     506                 :          5 :         rc = spdk_iobuf_register_module("ut_module0");
     507                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     508                 :            : 
     509                 :          5 :         rc = spdk_iobuf_register_module("ut_module1");
     510                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     511                 :            : 
     512                 :            :         /* First check that channel initialization fails when it's not possible to fill in the cache
     513                 :            :          * from the pool.
     514                 :            :          */
     515                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[0], "ut_module0", 5, 1);
     516                 :          5 :         CU_ASSERT_EQUAL(rc, -ENOMEM);
     517                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[0], "ut_module0", 1, 5);
     518                 :          5 :         CU_ASSERT_EQUAL(rc, -ENOMEM);
     519                 :            : 
     520                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[0], "ut_module0", 4, 4);
     521                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     522                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[1], "ut_module1", 4, 4);
     523                 :          5 :         CU_ASSERT_EQUAL(rc, -ENOMEM);
     524                 :            : 
     525                 :          5 :         spdk_iobuf_channel_fini(&iobuf_ch[0]);
     526                 :          5 :         poll_threads();
     527                 :            : 
     528                 :            :         /* Initialize one channel with cache, acquire buffers, and check that a second one can be
     529                 :            :          * created once the buffers acquired from the first one are returned to the pool
     530                 :            :          */
     531                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[0], "ut_module0", 2, 2);
     532                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     533                 :            : 
     534         [ +  + ]:         20 :         for (i = 0; i < 3; ++i) {
     535                 :         15 :                 mod0_entries[i].buf = spdk_iobuf_get(&iobuf_ch[0], LARGE_BUFSIZE, &mod0_entries[i].iobuf,
     536                 :            :                                                      ut_iobuf_get_buf_cb);
     537                 :         15 :                 CU_ASSERT_PTR_NOT_NULL(mod0_entries[i].buf);
     538                 :            :         }
     539                 :            : 
     540                 :            :         /* The channels can be temporarily greedy, holding more buffers than their configured cache
     541                 :            :          * size. We can only guarantee that we can create a channel if all outstanding buffers
     542                 :            :          * have been returned. */
     543         [ +  + ]:         20 :         for (i = 0; i < 3; ++i) {
     544                 :         15 :                 spdk_iobuf_put(&iobuf_ch[0], mod0_entries[i].buf, LARGE_BUFSIZE);
     545                 :            :         }
     546                 :            : 
     547                 :            :         /* The last buffer should be released back to the pool, so we should be able to create a new
     548                 :            :          * channel
     549                 :            :          */
     550                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[1], "ut_module1", 2, 2);
     551                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     552                 :            : 
     553                 :          5 :         spdk_iobuf_channel_fini(&iobuf_ch[0]);
     554                 :          5 :         spdk_iobuf_channel_fini(&iobuf_ch[1]);
     555                 :          5 :         poll_threads();
     556                 :            : 
     557                 :            :         /* Check that the pool is only used when the cache is empty and that the cache guarantees a
     558                 :            :          * certain set of buffers
     559                 :            :          */
     560                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[0], "ut_module0", 2, 2);
     561                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     562                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch[1], "ut_module1", 1, 1);
     563                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     564                 :            : 
     565                 :          5 :         uint32_t buffer_sizes[] = { SMALL_BUFSIZE, LARGE_BUFSIZE };
     566         [ +  + ]:         15 :         for (i = 0; i < SPDK_COUNTOF(buffer_sizes); ++i) {
     567                 :         10 :                 bufsize = buffer_sizes[i];
     568                 :            : 
     569         [ +  + ]:         40 :                 for (j = 0; j < 3; ++j) {
     570                 :         30 :                         entry = &mod0_entries[j];
     571                 :         30 :                         entry->buf = spdk_iobuf_get(&iobuf_ch[0], bufsize, &entry->iobuf,
     572                 :            :                                                     ut_iobuf_get_buf_cb);
     573                 :         30 :                         CU_ASSERT_PTR_NOT_NULL(entry->buf);
     574                 :            :                 }
     575                 :            : 
     576                 :         10 :                 mod1_entries[0].buf = spdk_iobuf_get(&iobuf_ch[1], bufsize, &mod1_entries[0].iobuf,
     577                 :            :                                                      ut_iobuf_get_buf_cb);
     578                 :         10 :                 CU_ASSERT_PTR_NOT_NULL(mod1_entries[0].buf);
     579                 :            : 
     580                 :            :                 /* The whole pool is exhausted now */
     581                 :         10 :                 mod1_entries[1].buf = spdk_iobuf_get(&iobuf_ch[1], bufsize, &mod1_entries[1].iobuf,
     582                 :            :                                                      ut_iobuf_get_buf_cb);
     583                 :         10 :                 CU_ASSERT_PTR_NULL(mod1_entries[1].buf);
     584                 :         10 :                 mod0_entries[3].buf = spdk_iobuf_get(&iobuf_ch[0], bufsize, &mod0_entries[3].iobuf,
     585                 :            :                                                      ut_iobuf_get_buf_cb);
     586                 :         10 :                 CU_ASSERT_PTR_NULL(mod0_entries[3].buf);
     587                 :            : 
     588                 :            :                 /* If there are outstanding requests waiting for a buffer, they should have priority
     589                 :            :                  * over filling in the cache, even if they're from different modules.
     590                 :            :                  */
     591                 :         10 :                 spdk_iobuf_put(&iobuf_ch[0], mod0_entries[2].buf, bufsize);
     592                 :            :                 /* Also make sure the queue is FIFO and doesn't care about which module requested
     593                 :            :                  * and which module released the buffer.
     594                 :            :                  */
     595                 :         10 :                 CU_ASSERT_PTR_NOT_NULL(mod1_entries[1].buf);
     596                 :         10 :                 CU_ASSERT_PTR_NULL(mod0_entries[3].buf);
     597                 :            : 
     598                 :            :                 /* Return the buffers back */
     599                 :         10 :                 spdk_iobuf_entry_abort(&iobuf_ch[0], &mod0_entries[3].iobuf, bufsize);
     600         [ +  + ]:         30 :                 for (j = 0; j < 2; ++j) {
     601                 :         20 :                         spdk_iobuf_put(&iobuf_ch[0], mod0_entries[j].buf, bufsize);
     602                 :         20 :                         spdk_iobuf_put(&iobuf_ch[1], mod1_entries[j].buf, bufsize);
     603                 :            :                 }
     604                 :            :         }
     605                 :            : 
     606                 :          5 :         spdk_iobuf_channel_fini(&iobuf_ch[0]);
     607                 :          5 :         spdk_iobuf_channel_fini(&iobuf_ch[1]);
     608                 :          5 :         poll_threads();
     609                 :            : 
     610                 :          5 :         spdk_iobuf_finish(ut_iobuf_finish_cb, &finish);
     611                 :          5 :         poll_threads();
     612                 :            : 
     613                 :          5 :         CU_ASSERT_EQUAL(finish, 1);
     614                 :            : 
     615                 :          5 :         free_threads();
     616                 :          5 :         free_cores();
     617                 :          5 : }
     618                 :            : 
     619                 :            : static void
     620                 :         10 : ut_iobuf_get_buf2_cb(struct spdk_iobuf_entry *entry, void *buf)
     621                 :            : {
     622                 :         10 :         struct ut_iobuf_entry *ut_entry = SPDK_CONTAINEROF(entry, struct ut_iobuf_entry, iobuf);
     623                 :            : 
     624                 :         10 :         CU_ASSERT_PTR_NOT_NULL(ut_entry->buf);
     625                 :         10 :         CU_ASSERT_PTR_NULL(ut_entry->buf2);
     626                 :            : 
     627                 :         10 :         ut_entry->buf2 = buf;
     628                 :         10 : }
     629                 :            : 
     630                 :            : static void
     631                 :         10 : ut_iobuf_get_buf1_cb(struct spdk_iobuf_entry *entry, void *buf)
     632                 :            : {
     633                 :         10 :         struct ut_iobuf_entry *ut_entry = SPDK_CONTAINEROF(entry, struct ut_iobuf_entry, iobuf);
     634                 :            :         void *buf2;
     635                 :            : 
     636                 :         10 :         CU_ASSERT_PTR_NULL(ut_entry->buf);
     637                 :         10 :         CU_ASSERT_PTR_NULL(ut_entry->buf2);
     638                 :         10 :         ut_entry->buf = buf;
     639                 :            : 
     640                 :         10 :         buf2 = spdk_iobuf_get(ut_entry->ioch, SMALL_BUFSIZE, &ut_entry->iobuf,
     641                 :            :                               ut_iobuf_get_buf2_cb);
     642                 :         10 :         CU_ASSERT_PTR_NULL(buf2);
     643                 :         10 : }
     644                 :            : 
     645                 :            : static void
     646                 :          5 : iobuf_priority(void)
     647                 :            : {
     648                 :          5 :         struct spdk_iobuf_opts opts = {
     649                 :            :                 .small_pool_count = 2,
     650                 :            :                 .large_pool_count = 2,
     651                 :            :                 .small_bufsize = SMALL_BUFSIZE,
     652                 :            :                 .large_bufsize = LARGE_BUFSIZE,
     653                 :            :         };
     654                 :          5 :         struct ut_iobuf_entry entries[4] = {};
     655                 :          4 :         struct spdk_iobuf_channel iobuf_ch;
     656                 :          5 :         int rc, finish = 0;
     657                 :            :         uint32_t i;
     658                 :            : 
     659                 :          5 :         allocate_cores(1);
     660                 :          5 :         allocate_threads(1);
     661                 :            : 
     662                 :          5 :         set_thread(0);
     663                 :            : 
     664                 :            :         /* We cannot use spdk_iobuf_set_opts(), as it won't allow us to use such small pools */
     665                 :          5 :         g_iobuf.opts = opts;
     666                 :          5 :         rc = spdk_iobuf_initialize();
     667                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     668                 :            : 
     669                 :          5 :         rc = spdk_iobuf_register_module("ut_module");
     670                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     671                 :          5 :         rc = spdk_iobuf_channel_init(&iobuf_ch, "ut_module", 0, 0);
     672                 :          5 :         CU_ASSERT_EQUAL(rc, 0);
     673                 :            : 
     674         [ +  + ]:         25 :         for (i = 0; i < SPDK_COUNTOF(entries); ++i) {
     675                 :         20 :                 entries[i].ioch = &iobuf_ch;
     676                 :            :         }
     677                 :            : 
     678                 :            :         /* Check that requests for an iobuf called from within the iobuf_get_cb are prioritized */
     679                 :          5 :         entries[0].buf = spdk_iobuf_get(&iobuf_ch, SMALL_BUFSIZE, NULL, NULL);
     680                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entries[0].buf);
     681                 :          5 :         entries[1].buf = spdk_iobuf_get(&iobuf_ch, SMALL_BUFSIZE, NULL, NULL);
     682                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entries[1].buf);
     683                 :            : 
     684                 :            :         /* Try to acquire two iobufs twice */
     685                 :          5 :         entries[2].buf = spdk_iobuf_get(&iobuf_ch, SMALL_BUFSIZE, &entries[2].iobuf,
     686                 :            :                                         ut_iobuf_get_buf1_cb);
     687                 :          5 :         CU_ASSERT_PTR_NULL(entries[2].buf);
     688                 :          5 :         entries[3].buf = spdk_iobuf_get(&iobuf_ch, SMALL_BUFSIZE, &entries[3].iobuf,
     689                 :            :                                         ut_iobuf_get_buf1_cb);
     690                 :          5 :         CU_ASSERT_PTR_NULL(entries[3].buf);
     691                 :            : 
     692                 :            :         /* Return one of the iobufs - the first entry on the wait queue should get it */
     693                 :          5 :         spdk_iobuf_put(&iobuf_ch, entries[0].buf, SMALL_BUFSIZE);
     694                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entries[2].buf);
     695                 :          5 :         CU_ASSERT_PTR_NULL(entries[3].buf);
     696                 :            : 
     697                 :            :         /* Return the second one, this time the same entry should get it, because it requested
     698                 :            :          * inside its iobuf_get_cb */
     699                 :          5 :         spdk_iobuf_put(&iobuf_ch, entries[1].buf, SMALL_BUFSIZE);
     700                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entries[2].buf2);
     701                 :          5 :         CU_ASSERT_PTR_NULL(entries[3].buf);
     702                 :            : 
     703                 :            :         /* Release it again, now the last entry should finally get it */
     704                 :          5 :         spdk_iobuf_put(&iobuf_ch, entries[2].buf, SMALL_BUFSIZE);
     705                 :          5 :         spdk_iobuf_put(&iobuf_ch, entries[2].buf2, SMALL_BUFSIZE);
     706                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entries[3].buf);
     707                 :          5 :         CU_ASSERT_PTR_NOT_NULL(entries[3].buf2);
     708                 :          5 :         spdk_iobuf_put(&iobuf_ch, entries[3].buf, SMALL_BUFSIZE);
     709                 :          5 :         spdk_iobuf_put(&iobuf_ch, entries[3].buf2, SMALL_BUFSIZE);
     710                 :            : 
     711                 :          5 :         spdk_iobuf_channel_fini(&iobuf_ch);
     712                 :          5 :         poll_threads();
     713                 :            : 
     714                 :          5 :         spdk_iobuf_finish(ut_iobuf_finish_cb, &finish);
     715                 :          5 :         poll_threads();
     716                 :            : 
     717                 :          5 :         CU_ASSERT_EQUAL(finish, 1);
     718                 :            : 
     719                 :          5 :         free_threads();
     720                 :          5 :         free_cores();
     721                 :          5 : }
     722                 :            : 
     723                 :            : int
     724                 :          5 : main(int argc, char **argv)
     725                 :            : {
     726                 :          5 :         CU_pSuite       suite = NULL;
     727                 :            :         unsigned int    num_failures;
     728                 :            : 
     729                 :          5 :         CU_initialize_registry();
     730                 :            : 
     731                 :          5 :         suite = CU_add_suite("io_channel", NULL, NULL);
     732                 :          5 :         CU_ADD_TEST(suite, iobuf);
     733                 :          5 :         CU_ADD_TEST(suite, iobuf_cache);
     734                 :          5 :         CU_ADD_TEST(suite, iobuf_priority);
     735                 :            : 
     736                 :          5 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     737                 :          5 :         CU_cleanup_registry();
     738                 :          5 :         return num_failures;
     739                 :            : }

Generated by: LCOV version 1.14