mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
memblock: extend test coverage
* add tests that trigger reallocation of memblock structures from memblock itself via memblock_double_array() * add tests for memblock_alloc_exact_nid_raw() that verify that requested node and memory range constraints are respected. -----BEGIN PGP SIGNATURE----- iQFMBAABCAA2FiEEeOVYVaWZL5900a/pOQOGJssO/ZEFAmOYL14YHG1pa2UucmFw b3BvcnRAZ21haWwuY29tAAoJEDkDhibLDv2RZdcH/2AE447oXzVO2lzOgkqQH1EX xJdaa7hu00h2Euzv2lgcOHroHGXDP8wYjUV2cEyNZMP0WOMiO8i6rwIKmrzWufcm R+ZoKPQV/Nc+7rIycpW455yLxcgsVIpUILK2BQEkDCGYugSHKb7IYdcA9KDJwtmR xIG9j8nsuwWJtmtAuQqNOBmsc5FzKNYFa/RtDiJoMFmQNK3UqB8G8VCASdP0DYvH 7MXPcyRmlwpmOsKoNKi2/wQBsiag8/PLgcZv5vYg+E6no1tMG6u7pgDS12Sn6ZvA I8gThJ8HNAo0d1O2SnbkicMx2CqrPFSub3QXaEFjCZF5mdBcirxHc/VBKj50TXU= =iXEA -----END PGP SIGNATURE----- Merge tag 'memblock-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock Pull memblock updates from Mike Rapoport: "Extend test coverage: - add tests that trigger reallocation of memblock structures from memblock itself via memblock_double_array() - add tests for memblock_alloc_exact_nid_raw() that verify that requested node and memory range constraints are respected" * tag 'memblock-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock: memblock tests: remove completed TODO item memblock tests: add generic NUMA tests for memblock_alloc_exact_nid_raw memblock tests: add bottom-up NUMA tests for memblock_alloc_exact_nid_raw memblock tests: add top-down NUMA tests for memblock_alloc_exact_nid_raw memblock tests: introduce range tests for memblock_alloc_exact_nid_raw memblock test: Update TODO list memblock test: Add test to memblock_reserve() 129th region memblock test: Add test to memblock_add() 129th region
This commit is contained in:
commit
ad76bf1ff1
@ -7,7 +7,7 @@ CFLAGS += -I. -I../../include -Wall -O2 -fsanitize=address \
|
||||
LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||
TARGETS = main
|
||||
TEST_OFILES = tests/alloc_nid_api.o tests/alloc_helpers_api.o tests/alloc_api.o \
|
||||
tests/basic_api.o tests/common.o
|
||||
tests/basic_api.o tests/common.o tests/alloc_exact_nid_api.o
|
||||
DEP_OFILES = memblock.o lib/slab.o mmzone.o slab.o
|
||||
OFILES = main.o $(DEP_OFILES) $(TEST_OFILES)
|
||||
EXTR_SRC = ../../../mm/memblock.c
|
||||
|
@ -1,17 +1,5 @@
|
||||
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):
|
||||
+ 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
|
||||
1. Add tests for memblock_alloc_node() to check if the correct NUMA node is set
|
||||
for the new region
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "tests/alloc_api.h"
|
||||
#include "tests/alloc_helpers_api.h"
|
||||
#include "tests/alloc_nid_api.h"
|
||||
#include "tests/alloc_exact_nid_api.h"
|
||||
#include "tests/common.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@ -12,6 +13,7 @@ int main(int argc, char **argv)
|
||||
memblock_alloc_checks();
|
||||
memblock_alloc_helpers_checks();
|
||||
memblock_alloc_nid_checks();
|
||||
memblock_alloc_exact_nid_checks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1113
tools/testing/memblock/tests/alloc_exact_nid_api.c
Normal file
1113
tools/testing/memblock/tests/alloc_exact_nid_api.c
Normal file
File diff suppressed because it is too large
Load Diff
25
tools/testing/memblock/tests/alloc_exact_nid_api.h
Normal file
25
tools/testing/memblock/tests/alloc_exact_nid_api.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef _MEMBLOCK_ALLOC_EXACT_NID_H
|
||||
#define _MEMBLOCK_ALLOC_EXACT_NID_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int memblock_alloc_exact_nid_checks(void);
|
||||
int __memblock_alloc_exact_nid_numa_checks(void);
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
static inline int memblock_alloc_exact_nid_numa_checks(void)
|
||||
{
|
||||
__memblock_alloc_exact_nid_numa_checks();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline int memblock_alloc_exact_nid_numa_checks(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NUMA */
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
||||
#include "common.h"
|
||||
|
||||
int memblock_alloc_nid_checks(void);
|
||||
int memblock_alloc_exact_nid_range_checks(void);
|
||||
int __memblock_alloc_nid_numa_checks(void);
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
|
@ -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();
|
||||
|
||||
@ -799,6 +892,96 @@ static int memblock_reserve_near_max_check(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A test that trying to reserve the 129th memory block.
|
||||
* Expect to trigger memblock_double_array() to double the
|
||||
* memblock.memory.max, find a new valid memory as
|
||||
* reserved.regions.
|
||||
*/
|
||||
static int memblock_reserve_many_check(void)
|
||||
{
|
||||
int i;
|
||||
void *orig_region;
|
||||
struct region r = {
|
||||
.base = SZ_16K,
|
||||
.size = SZ_16K,
|
||||
};
|
||||
phys_addr_t memory_base = SZ_128K;
|
||||
phys_addr_t new_reserved_regions_size;
|
||||
|
||||
PREFIX_PUSH();
|
||||
|
||||
reset_memblock_regions();
|
||||
memblock_allow_resize();
|
||||
|
||||
/* Add a valid memory region used by double_array(). */
|
||||
dummy_physical_memory_init();
|
||||
memblock_add(dummy_physical_memory_base(), MEM_SIZE);
|
||||
|
||||
for (i = 0; i < INIT_MEMBLOCK_REGIONS; i++) {
|
||||
/* Reserve some fakes memory region to fulfill the memblock. */
|
||||
memblock_reserve(memory_base, MEM_SIZE);
|
||||
|
||||
ASSERT_EQ(memblock.reserved.cnt, i + 1);
|
||||
ASSERT_EQ(memblock.reserved.total_size, (i + 1) * MEM_SIZE);
|
||||
|
||||
/* Keep the gap so these memory region will not be merged. */
|
||||
memory_base += MEM_SIZE * 2;
|
||||
}
|
||||
|
||||
orig_region = memblock.reserved.regions;
|
||||
|
||||
/* This reserve the 129 memory_region, and makes it double array. */
|
||||
memblock_reserve(memory_base, MEM_SIZE);
|
||||
|
||||
/*
|
||||
* This is the memory region size used by the doubled reserved.regions,
|
||||
* and it has been reserved due to it has been used. The size is used to
|
||||
* calculate the total_size that the memblock.reserved have now.
|
||||
*/
|
||||
new_reserved_regions_size = PAGE_ALIGN((INIT_MEMBLOCK_REGIONS * 2) *
|
||||
sizeof(struct memblock_region));
|
||||
/*
|
||||
* The double_array() will find a free memory region as the new
|
||||
* reserved.regions, and the used memory region will be reserved, so
|
||||
* there will be one more region exist in the reserved memblock. And the
|
||||
* one more reserved region's size is new_reserved_regions_size.
|
||||
*/
|
||||
ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 2);
|
||||
ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
|
||||
new_reserved_regions_size);
|
||||
ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
|
||||
|
||||
/*
|
||||
* Now memblock_double_array() works fine. Let's check after the
|
||||
* double_array(), the memblock_reserve() still works as normal.
|
||||
*/
|
||||
memblock_reserve(r.base, r.size);
|
||||
ASSERT_EQ(memblock.reserved.regions[0].base, r.base);
|
||||
ASSERT_EQ(memblock.reserved.regions[0].size, r.size);
|
||||
|
||||
ASSERT_EQ(memblock.reserved.cnt, INIT_MEMBLOCK_REGIONS + 3);
|
||||
ASSERT_EQ(memblock.reserved.total_size, (INIT_MEMBLOCK_REGIONS + 1) * MEM_SIZE +
|
||||
new_reserved_regions_size +
|
||||
r.size);
|
||||
ASSERT_EQ(memblock.reserved.max, INIT_MEMBLOCK_REGIONS * 2);
|
||||
|
||||
dummy_physical_memory_cleanup();
|
||||
|
||||
/*
|
||||
* The current reserved.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.reserved.regions = orig_region;
|
||||
memblock.reserved.cnt = INIT_MEMBLOCK_RESERVED_REGIONS;
|
||||
|
||||
test_pass_pop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int memblock_reserve_checks(void)
|
||||
{
|
||||
prefix_reset();
|
||||
@ -813,6 +996,7 @@ static int memblock_reserve_checks(void)
|
||||
memblock_reserve_twice_check();
|
||||
memblock_reserve_between_check();
|
||||
memblock_reserve_near_max_check();
|
||||
memblock_reserve_many_check();
|
||||
|
||||
prefix_pop();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -10,14 +10,19 @@
|
||||
#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,
|
||||
/* Perform raw allocations (no zeroing of memory). */
|
||||
TEST_F_RAW = 0x1,
|
||||
/* Perform allocations on the exact node specified. */
|
||||
TEST_F_EXACT = 0x2
|
||||
};
|
||||
|
||||
/**
|
||||
@ -124,6 +129,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);
|
||||
|
Loading…
Reference in New Issue
Block a user