From 8a4b79778f8b3149d663face83d37fbf96e12d05 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Wed, 28 Sep 2022 13:37:02 +0500 Subject: vppinfra: fix pool free bitmap allocation Using clib_bitmap_vec_validate makes free bitmap vector to be x64 times bigger (assuming x86_64) than necessary when non-zero and possible oom due (u32)(0 - 1) math with zero alloc. Fix it with clib_bitmap_validate which takes bit size, not index and ensure at least one bit is allocated. Type: fix Change-Id: I7e191f4e2fb3722a06bb800e1d075f7c7e2dcec9 Signed-off-by: Vladislav Grishenko --- src/vppinfra/CMakeLists.txt | 1 + src/vppinfra/pool.h | 2 +- src/vppinfra/test_pool_alloc.c | 56 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/vppinfra/test_pool_alloc.c diff --git a/src/vppinfra/CMakeLists.txt b/src/vppinfra/CMakeLists.txt index e24e0493ca9..204858d30a8 100644 --- a/src/vppinfra/CMakeLists.txt +++ b/src/vppinfra/CMakeLists.txt @@ -247,6 +247,7 @@ if(VPP_BUILD_VPPINFRA_TESTS) macros maplog pmalloc + pool_alloc pool_iterate ptclosure random diff --git a/src/vppinfra/pool.h b/src/vppinfra/pool.h index ea22af4a68b..968614e0b9d 100644 --- a/src/vppinfra/pool.h +++ b/src/vppinfra/pool.h @@ -333,7 +333,7 @@ _pool_alloc (void **pp, uword n_elts, uword align, void *heap, uword elt_sz) ph = pool_header (pp[0]); vec_resize (ph->free_indices, n_elts); vec_dec_len (ph->free_indices, n_elts); - clib_bitmap_vec_validate (ph->free_bitmap, len + n_elts - 1); + clib_bitmap_validate (ph->free_bitmap, (len + n_elts) ?: 1); } #define pool_alloc_aligned_heap(P, N, A, H) \ diff --git a/src/vppinfra/test_pool_alloc.c b/src/vppinfra/test_pool_alloc.c new file mode 100644 index 00000000000..57b78b8ad9e --- /dev/null +++ b/src/vppinfra/test_pool_alloc.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2023 Yandex LLC. + */ + +#include + +/* can be a very large size */ +#define NELTS 1024 + +int +main (int argc, char *argv[]) +{ + u32 *junk = 0; + int i; + u32 *tp = 0; + u32 *indices = 0; + + clib_mem_init (0, 3ULL << 30); + + vec_validate (indices, NELTS - 1); + vec_set_len (indices, 0); + + /* zero size allocation is ok */ + pool_alloc (tp, 0); + + fformat (stdout, "%d pool elts of empty pool\n", pool_elts (tp)); + + pool_validate (tp); + + pool_alloc (tp, NELTS); + + for (i = 0; i < NELTS; i++) + { + pool_get (tp, junk); + vec_add1 (indices, junk - tp); + *junk = i; + } + + for (i = 0; i < NELTS; i++) + { + junk = pool_elt_at_index (tp, indices[i]); + ASSERT (*junk == i); + } + + fformat (stdout, "%d pool elts before deletes\n", pool_elts (tp)); + + pool_put_index (tp, indices[12]); + pool_put_index (tp, indices[43]); + + fformat (stdout, "%d pool elts after deletes\n", pool_elts (tp)); + + pool_validate (tp); + + pool_free (tp); + return 0; +} -- cgit 1.2.3-korg