2022-10-11 07:05:50

by Huang, Shaoqin

[permalink] [raw]
Subject: [PATCH v4 0/3] Add tests trying to memblock_add() or memblock_reserve() 129th region

From: Shaoqin Huang <[email protected]>

These tests is aimed for testing the memblock_double_array() can work normal. It
will using the dummy_physical_memory_init() to add the valid memory region into
the memblock.memory, and this memory region will be choosed when
memblock_double_array() to allocate the new memory region to double the regions.
Thus the new memory.regions or reserved.regions will occupy the valid memory
region, and the memory.max and reserved.max also being doubled. Check all of
these changed stuff, to make sure it actually success.

Changelog:
----------
v4:
- Increase the MEM_SIZE to SZ_32K. And makes the calculation process in
memblock_add_many_check() more simpler.
v3:
- Avoid to allocated multiple memory region from dummy_physical_memory_base(),
split the memory into different part instead.
- Some comments improvement.
v2:
- Modify the get_memory_block_base() to dummy_physical_memory_base().
- memory_add() the memory which is allocated from dummy_physical_memory_init()
instead of some faked memory.
- Add more comments to illustrate the test process.
- Add a function dummy_physical_memory_cleanup_many() to free multiple memory
which is allocated from dummy_physical_memory_init().

Shaoqin Huang (3):
memblock test: Add test to memblock_add() 129th region
memblock test: Add test to memblock_reserve() 129th region
memblock test: Update TODO list

tools/testing/memblock/TODO | 11 +-
tools/testing/memblock/tests/basic_api.c | 184 +++++++++++++++++++++++
tools/testing/memblock/tests/common.c | 7 +-
tools/testing/memblock/tests/common.h | 6 +-
4 files changed, 196 insertions(+), 12 deletions(-)

--
2.34.1


2022-10-11 07:13:00

by Huang, Shaoqin

[permalink] [raw]
Subject: [PATCH v4 1/3] memblock test: Add test to memblock_add() 129th region

From: Shaoqin Huang <[email protected]>

Add 129th region into the memblock, and this will trigger the
memblock_double_array() function, this needs valid memory regions. So
using dummy_physical_memory_init() to allocate a large enough memory
region, and split it into a large enough memory which can be choosed by
memblock_double_array(), and the left memory will be split into small
memory region, and add them into the memblock. It make sure the
memblock_double_array() will always choose the valid memory region that
is allocated by the dummy_physical_memory_init().
So memblock_double_array() must success.

Another thing should be done is to restore the memory.regions after
memblock_double_array(), due to now the memory.regions is pointing to a
memory region allocated by dummy_physical_memory_init(). And it will
affect the subsequent tests if we don't restore the memory region. So
simply record the origin region, and restore it after the test.

Signed-off-by: Shaoqin Huang <[email protected]>
---
tools/testing/memblock/tests/basic_api.c | 93 ++++++++++++++++++++++++
tools/testing/memblock/tests/common.c | 7 +-
tools/testing/memblock/tests/common.h | 6 +-
3 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/tools/testing/memblock/tests/basic_api.c b/tools/testing/memblock/tests/basic_api.c
index a13a57ba0815..4d61a4b474be 100644
--- a/tools/testing/memblock/tests/basic_api.c
+++ b/tools/testing/memblock/tests/basic_api.c
@@ -423,6 +423,98 @@ static int memblock_add_near_max_check(void)
return 0;
}

+/*
+ * A test that trying to add the 129th memory block.
+ * Expect to trigger memblock_double_array() to double the
+ * memblock.memory.max, find a new valid memory as
+ * memory.regions.
+ */
+static int memblock_add_many_check(void)
+{
+ int i;
+ void *orig_region;
+ struct region r = {
+ .base = SZ_16K,
+ .size = SZ_16K,
+ };
+ phys_addr_t new_memory_regions_size;
+ phys_addr_t base, size = SZ_64;
+ phys_addr_t gap_size = SZ_64;
+
+ PREFIX_PUSH();
+
+ reset_memblock_regions();
+ memblock_allow_resize();
+
+ dummy_physical_memory_init();
+ /*
+ * We allocated enough memory by using dummy_physical_memory_init(), and
+ * split it into small block. First we split a large enough memory block
+ * as the memory region which will be choosed by memblock_double_array().
+ */
+ base = PAGE_ALIGN(dummy_physical_memory_base());
+ new_memory_regions_size = PAGE_ALIGN(INIT_MEMBLOCK_REGIONS * 2 *
+ sizeof(struct memblock_region));
+ memblock_add(base, new_memory_regions_size);
+
+ /* This is the base of small memory block. */
+ base += new_memory_regions_size + gap_size;
+
+ orig_region = memblock.memory.regions;
+
+ for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) {
+ /*
+ * Add these small block to fulfill the memblock. We keep a
+ * gap between the nearby memory to avoid being merged.
+ */
+ memblock_add(base, size);
+ base += size + gap_size;
+
+ ASSERT_EQ(memblock.memory.cnt, i + 2);
+ ASSERT_EQ(memblock.memory.total_size, new_memory_regions_size +
+ (i + 1) * size);
+ }
+
+ /*
+ * At there, memblock_double_array() has been succeed, check if it
+ * update the memory.max.
+ */
+ ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2);
+
+ /* memblock_double_array() will reserve the memory it used. Check it. */
+ ASSERT_EQ(memblock.reserved.cnt, 1);
+ ASSERT_EQ(memblock.reserved.total_size, new_memory_regions_size);
+
+ /*
+ * Now memblock_double_array() works fine. Let's check after the
+ * double_array(), the memblock_add() still works as normal.
+ */
+ memblock_add(r.base, r.size);
+ ASSERT_EQ(memblock.memory.regions[0].base, r.base);
+ ASSERT_EQ(memblock.memory.regions[0].size, r.size);
+
+ ASSERT_EQ(memblock.memory.cnt, INIT_MEMBLOCK_REGIONS + 2);
+ ASSERT_EQ(memblock.memory.total_size, INIT_MEMBLOCK_REGIONS * size +
+ new_memory_regions_size +
+ r.size);
+ ASSERT_EQ(memblock.memory.max, INIT_MEMBLOCK_REGIONS * 2);
+
+ dummy_physical_memory_cleanup();
+
+ /*
+ * The current memory.regions is occupying a range of memory that
+ * allocated from dummy_physical_memory_init(). After free the memory,
+ * we must not use it. So restore the origin memory region to make sure
+ * the tests can run as normal and not affected by the double array.
+ */
+ memblock.memory.regions = orig_region;
+ memblock.memory.cnt = INIT_MEMBLOCK_REGIONS;
+
+ test_pass_pop();
+
+ return 0;
+}
+
static int memblock_add_checks(void)
{
prefix_reset();
@@ -438,6 +530,7 @@ static int memblock_add_checks(void)
memblock_add_twice_check();
memblock_add_between_check();
memblock_add_near_max_check();
+ memblock_add_many_check();

prefix_pop();

diff --git a/tools/testing/memblock/tests/common.c b/tools/testing/memblock/tests/common.c
index 3f795047bbe1..f43b6f414983 100644
--- a/tools/testing/memblock/tests/common.c
+++ b/tools/testing/memblock/tests/common.c
@@ -5,8 +5,6 @@
#include <linux/memory_hotplug.h>
#include <linux/build_bug.h>

-#define INIT_MEMBLOCK_REGIONS 128
-#define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
#define PREFIXES_MAX 15
#define DELIM ": "
#define BASIS 10000
@@ -115,6 +113,11 @@ void dummy_physical_memory_cleanup(void)
free(memory_block.base);
}

+phys_addr_t dummy_physical_memory_base(void)
+{
+ return (phys_addr_t)memory_block.base;
+}
+
static void usage(const char *prog)
{
BUILD_BUG_ON(ARRAY_SIZE(help_opts) != ARRAY_SIZE(long_opts) - 1);
diff --git a/tools/testing/memblock/tests/common.h b/tools/testing/memblock/tests/common.h
index d6bbbe63bfc3..cc82b85151b6 100644
--- a/tools/testing/memblock/tests/common.h
+++ b/tools/testing/memblock/tests/common.h
@@ -10,9 +10,12 @@
#include <linux/printk.h>
#include <../selftests/kselftest.h>

-#define MEM_SIZE SZ_16K
+#define MEM_SIZE SZ_32K
#define NUMA_NODES 8

+#define INIT_MEMBLOCK_REGIONS 128
+#define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
+
enum test_flags {
/* No special request. */
TEST_F_NONE = 0x0,
@@ -124,6 +127,7 @@ void setup_memblock(void);
void setup_numa_memblock(const unsigned int node_fracs[]);
void dummy_physical_memory_init(void);
void dummy_physical_memory_cleanup(void);
+phys_addr_t dummy_physical_memory_base(void);
void parse_args(int argc, char **argv);

void test_fail(void);
--
2.34.1

2022-10-11 07:34:52

by Huang, Shaoqin

[permalink] [raw]
Subject: [PATCH v4 3/3] memblock test: Update TODO list

From: Shaoqin Huang <[email protected]>

Remove the completed items from TODO list.

Signed-off-by: Shaoqin Huang <[email protected]>
---
tools/testing/memblock/TODO | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/tools/testing/memblock/TODO b/tools/testing/memblock/TODO
index 33044c634ea7..503cc96fcdc3 100644
--- a/tools/testing/memblock/TODO
+++ b/tools/testing/memblock/TODO
@@ -1,17 +1,10 @@
TODO
=====

-1. Add tests trying to memblock_add() or memblock_reserve() 129th region.
- This will trigger memblock_double_array(), make sure it succeeds.
- *Important:* These tests require valid memory ranges, use dummy physical
- memory block from common.c to implement them. It is also very
- likely that the current MEM_SIZE won't be enough for these
- test cases. Use realloc to adjust the size accordingly.
-
-2. Add test cases using this functions (implement them for both directions):
+1. Add test cases using this functions (implement them for both directions):
+ memblock_alloc_raw()
+ memblock_alloc_exact_nid_raw()
+ memblock_alloc_try_nid_raw()

-3. Add tests for memblock_alloc_node() to check if the correct NUMA node is set
+2. Add tests for memblock_alloc_node() to check if the correct NUMA node is set
for the new region
--
2.34.1

2022-10-24 18:03:48

by Mike Rapoport

[permalink] [raw]
Subject: Re: [PATCH v4 0/3] Add tests trying to memblock_add() or memblock_reserve() 129th region

On Tue, Oct 11, 2022 at 02:21:19PM +0800, [email protected] wrote:
> From: Shaoqin Huang <[email protected]>
>
> These tests is aimed for testing the memblock_double_array() can work normal. It
> will using the dummy_physical_memory_init() to add the valid memory region into
> the memblock.memory, and this memory region will be choosed when
> memblock_double_array() to allocate the new memory region to double the regions.
> Thus the new memory.regions or reserved.regions will occupy the valid memory
> region, and the memory.max and reserved.max also being doubled. Check all of
> these changed stuff, to make sure it actually success.
>
> Changelog:
> ----------
> v4:
> - Increase the MEM_SIZE to SZ_32K. And makes the calculation process in
> memblock_add_many_check() more simpler.
> v3:
> - Avoid to allocated multiple memory region from dummy_physical_memory_base(),
> split the memory into different part instead.
> - Some comments improvement.
> v2:
> - Modify the get_memory_block_base() to dummy_physical_memory_base().
> - memory_add() the memory which is allocated from dummy_physical_memory_init()
> instead of some faked memory.
> - Add more comments to illustrate the test process.
> - Add a function dummy_physical_memory_cleanup_many() to free multiple memory
> which is allocated from dummy_physical_memory_init().
>
> Shaoqin Huang (3):
> memblock test: Add test to memblock_add() 129th region
> memblock test: Add test to memblock_reserve() 129th region
> memblock test: Update TODO list
>
> tools/testing/memblock/TODO | 11 +-
> tools/testing/memblock/tests/basic_api.c | 184 +++++++++++++++++++++++
> tools/testing/memblock/tests/common.c | 7 +-
> tools/testing/memblock/tests/common.h | 6 +-
> 4 files changed, 196 insertions(+), 12 deletions(-)

Applied, thanks!

--
Sincerely yours,
Mike.