[LTP] [PATCH v3 1/2] lib: add .request_hugepages to reserve hugepage
Cyril Hrubis
chrubis@suse.cz
Wed Jan 22 15:31:33 CET 2020
Hi!
> Many of the ltp tests need to use hugepage in their testing, this allows
> the test can reserve hpages from system only via .request_hugepages = xx.
>
> If set non-zero number of request_hugepages, test will try to reserve the
> expected number of hugepage for testing in setup phase. If system does not
> have enough hpage for using, it will try the best to reserve 80% available
> number of hpages. For a system without hugetlb supporting, variable
> 'tst_hugepage' will be set to 0.
>
> Signed-off-by: Li Wang <liwang@redhat.com>
> ---
>
> Notes:
> v2 --> v3
> * rename .needs_hugepages to .request_hugepages
> * rename tst_no_hugepage to tst_hugepages
> * makes tst_request_hugepages() return tst_hugepages
> * call tst_sys_conf_save in tst_hugepage.c
>
> doc/test-writing-guidelines.txt | 38 ++++++++++++++++++++++
> include/tst_hugepage.h | 29 +++++++++++++++++
> include/tst_test.h | 13 ++++++++
> lib/newlib_tests/.gitignore | 1 +
> lib/newlib_tests/test20.c | 45 ++++++++++++++++++++++++++
> lib/tst_hugepage.c | 57 +++++++++++++++++++++++++++++++++
> lib/tst_test.c | 6 ++--
> 7 files changed, 187 insertions(+), 2 deletions(-)
> create mode 100644 include/tst_hugepage.h
> create mode 100644 lib/newlib_tests/test20.c
> create mode 100644 lib/tst_hugepage.c
>
> diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
> index 546bb7a49..7875690b9 100644
> --- a/doc/test-writing-guidelines.txt
> +++ b/doc/test-writing-guidelines.txt
> @@ -1933,6 +1933,44 @@ specified by the user plus some other heuristics.
>
> For full documentation see the comments in 'include/tst_fuzzy_sync.h'.
>
> +2.2.34 Reserving hugepages
> +^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Many of the ltp tests need to use hugepage in their testing, this allows the
> +test can reserve hugepages from system only via .request_hugepages = xx.
> +
> +If set non-zero number of request_hugepages, test will try to reserve the
> +expected number of hugepage for testing in setup phase. If system does not
> +have enough hpage for using, it will try the best to reserve 80% available
> +number of hpages. With success test stores the reserved hugepage number in
> +'tst_hugepages. For the system without hugetlb supporting, variable
> +'tst_hugepages' will be set to 0.
> +
> +Also, we do cleanup and restore work for the hpages resetting automatically.
> +
> +[source,c]
> +-------------------------------------------------------------------------------
> +#include "tst_test.h"
> +
> +static void run(void)
> +{
> + ...
> +
> + if (tst_hugepages == test.request_hugepages)
> + TEST(do_hpage_test);
> + else
> + ...
> + ...
> +}
I guess that it would be more instructive to check the value in the test
setup() here, because most of the test would just check if tst_hugepages
has been set to expected value.
static void setup(void)
{
if (tst_hugepages != test.requested_hugepages)
tst_brk(TCONF, "...");
}
> +struct tst_test test = {
> + ...
> + .test_all = run,
> + .request_hugepages = 2,
> + ...
> +};
> +-------------------------------------------------------------------------------
> +
> 2.3 Writing a testcase in shell
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> diff --git a/include/tst_hugepage.h b/include/tst_hugepage.h
> new file mode 100644
> index 000000000..10e0eaf47
> --- /dev/null
> +++ b/include/tst_hugepage.h
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Red Hat, Inc.
> + */
> +
> +#ifndef TST_HUGEPAGE__
> +#define TST_HUGEPAGE__
> +
> +#define PATH_HUGEPAGES "/sys/kernel/mm/hugepages/"
> +#define PATH_NR_HPAGES "/proc/sys/vm/nr_hugepages"
> +
> +/*
> + * Try the best to request a specified number of huge pages from system,
> + * it will store the reserved hpage number in tst_hugepages.
> + *
> + * Note: this depend on the status of system memory fragmentation.
> + */
> +int tst_request_hugepages(int hpages);
> +
> +/*
> + * This variable is used for recording the number of hugepages which system can
> + * provides. It will be equal to 'hpages' if tst_request_hugepages on success,
> + * otherwise set it to a number of hugepages that we were able to reserve.
> + *
> + * If system does not support hugetlb, then it will be set to 0.
> + */
> +extern unsigned int tst_hugepages;
> +
> +#endif /* TST_HUGEPAGE_H */
> diff --git a/include/tst_test.h b/include/tst_test.h
> index 21c7dfbdb..1026a422a 100644
> --- a/include/tst_test.h
> +++ b/include/tst_test.h
> @@ -37,6 +37,7 @@
> #include "tst_coredump.h"
> #include "tst_buffers.h"
> #include "tst_capability.h"
> +#include "tst_hugepage.h"
>
> /*
> * Reports testcase result.
> @@ -148,6 +149,18 @@ struct tst_test {
> */
> int all_filesystems:1;
>
> + /*
> + * If set non-zero number of request_hugepages, test will try to reserve the
> + * expected number of hugepage for testing in setup phase. If system does not
> + * have enough hpage for using, it will try the best to reserve 80% available
> + * number of hpages. With success test stores the reserved hugepage number in
> + * 'tst_hugepages. For the system without hugetlb supporting, variable
> + * 'tst_hugepages' will be set to 0.
> + *
> + * Also, we do cleanup and restore work for the hpages resetting automatically.
> + */
> + unsigned int request_hugepages;
> +
> /*
> * If set non-zero denotes number of test variant, the test is executed
> * variants times each time with tst_variant set to different number.
> diff --git a/lib/newlib_tests/.gitignore b/lib/newlib_tests/.gitignore
> index d4aa4935f..ab3a92c4c 100644
> --- a/lib/newlib_tests/.gitignore
> +++ b/lib/newlib_tests/.gitignore
> @@ -23,6 +23,7 @@ tst_strstatus
> test17
> test18
> test19
> +test20
> tst_expiration_timer
> test_exec
> test_exec_child
> diff --git a/lib/newlib_tests/test20.c b/lib/newlib_tests/test20.c
> new file mode 100644
> index 000000000..92e230976
> --- /dev/null
> +++ b/lib/newlib_tests/test20.c
> @@ -0,0 +1,45 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Li Wang <liwang@redhat.com>
> + */
> +
> +/*
> + * Tests .request_hugepages + .save_restore
> + */
> +
> +#include "tst_test.h"
> +#include "tst_hugepage.h"
> +#include "tst_sys_conf.h"
> +
> +static const char * const save_restore[] = {
> + "!/proc/sys/kernel/numa_balancing",
> + NULL,
> +};
> +
> +static void do_test(void) {
> +
> + int val, hpages;
> +
> + tst_res(TINFO, "tst_hugepages = %u", tst_hugepages);
> + SAFE_FILE_PRINTF("/proc/sys/kernel/numa_balancing", "1");
> +
> + hpages = test.request_hugepages;
> + SAFE_FILE_SCANF(PATH_NR_HPAGES, "%d", &val);
> + if (val != hpages)
> + tst_brk(TBROK, "nr_hugepages = %d, but expect %d", val, hpages);
> + else
> + tst_res(TPASS, "test .needs_hugepges");
> +
> + hpages = tst_request_hugepages(3);
> + SAFE_FILE_SCANF(PATH_NR_HPAGES, "%d", &val);
> + if (val != hpages)
> + tst_brk(TBROK, "nr_hugepages = %d, but expect %d", val, hpages);
> + else
> + tst_res(TPASS, "tst_request_hugepages");
> +}
> +
> +static struct tst_test test = {
> + .test_all = do_test,
> + .request_hugepages = 2,
> + .save_restore = save_restore,
> +};
> diff --git a/lib/tst_hugepage.c b/lib/tst_hugepage.c
> new file mode 100644
> index 000000000..c4385b9c6
> --- /dev/null
> +++ b/lib/tst_hugepage.c
> @@ -0,0 +1,57 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Red Hat, Inc.
> + */
> +
> +#define TST_NO_DEFAULT_MAIN
> +
> +#include "tst_test.h"
> +#include "tst_hugepage.h"
> +
> +unsigned int tst_hugepages;
> +
> +int tst_request_hugepages(int hpages)
> +{
> + int val;
> + long mem_avail, max_hpages;
> +
> + if (access(PATH_HUGEPAGES, F_OK)) {
> + tst_res(TCONF, "Huge page is not supported.");
I guess that this is something the test has to decide, i.e. I wouldn't
print anything here.
> + tst_hugepages = 0;
> + goto out;
> + }
> +
> + tst_hugepages = hpages;
> +
> + SAFE_FILE_PRINTF("/proc/sys/vm/drop_caches", "3");
Shouldn't we drop the caches only if MemAvailable is not present in
/proc/meminfo?
> + if (FILE_LINES_SCANF("/proc/meminfo",
> + "MemAvailable: %ld", &mem_avail)) {
> + /*
> + * Using "MemFree:" on kernel that doesn't have
> + * "MemAvailable:" in Meminfo
> + */
> + tst_res(TINFO, "MemAvailable: not found in /proc/meminfo");
> +
> + mem_avail = SAFE_READ_MEMINFO("MemFree:");
> + }
> +
> + max_hpages = mem_avail / SAFE_READ_MEMINFO("Hugepagesize:");
> +
> + if (hpages > max_hpages) {
> + tst_res(TINFO, "Requested number(%d) of hugepages is too large, "
> + "limiting to 80%% of the max hugepage count %ld",
> + hpages, max_hpages);
> + tst_hugepages = max_hpages * 0.8;
Why 80%?
Also I guess that we should check here that max_hpages * 0.8 > 1,
otherwise there is no reason to continue.
> + }
> +
> + tst_sys_conf_save("?/proc/sys/vm/nr_hugepages");
> + SAFE_FILE_PRINTF(PATH_NR_HPAGES, "%d", tst_hugepages);
> + SAFE_FILE_SCANF(PATH_NR_HPAGES, "%d", &val);
> + if (val != tst_hugepages)
> + tst_brk(TBROK, "nr_hugepages = %d, but expect %d", val, tst_hugepages);
> +
> + tst_res(TINFO, "%d hugepage(s) reserved", tst_hugepages);
> +out:
> + return tst_hugepages;
> +}
> diff --git a/lib/tst_test.c b/lib/tst_test.c
> index 8d7dee2cc..9a24cffc5 100644
> --- a/lib/tst_test.c
> +++ b/lib/tst_test.c
> @@ -890,6 +890,9 @@ static void do_setup(int argc, char *argv[])
> if (tst_test->all_filesystems)
> tst_test->needs_device = 1;
>
> + if (tst_test->request_hugepages)
> + tst_request_hugepages(tst_test->request_hugepages);
> +
> setup_ipc();
>
> if (tst_test->bufs)
> @@ -1006,8 +1009,7 @@ static void do_cleanup(void)
> tst_rmdir();
> }
>
> - if (tst_test->save_restore)
> - tst_sys_conf_restore(0);
> + tst_sys_conf_restore(0);
>
> if (tst_test->restore_wallclock)
> tst_wallclock_restore();
> --
> 2.20.1
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
More information about the ltp
mailing list