[LTP] [PATCH 1/1] syscalls/get_mempolicy01: Rewrite to new API
Cyril Hrubis
chrubis@suse.cz
Wed Dec 9 14:19:26 CET 2020
Hi!
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
> + * Copyright (c) Linux Test Project, 2009-2020
> + * Copyright (c) Crackerjack Project, 2007-2008, Hitachi, Ltd
> + *
> + * Authors:
> + * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>
> + * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>
> + * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
> + * Manas Kumar Nayak <maknayak@in.ibm.com> (original port to the legacy API)
> + */
Missing test description?
> #include "config.h"
> -#include <sys/types.h>
> -#include <sys/mman.h>
> -#include <getopt.h>
> -#include <string.h>
> -#include <stdlib.h>
> -#include <errno.h>
> -#include <stdio.h>
> -#include <unistd.h>
> -#include <libgen.h>
> -#if HAVE_NUMA_H
> +#include "tst_test.h"
> +
> +#ifdef HAVE_NUMA_V2
> #include <numa.h>
> -#endif
> -#if HAVE_NUMAIF_H
> #include <numaif.h>
> -#endif
>
> -#include "test.h"
> -#include "lapi/syscalls.h"
> -#include "include_j_h.h"
> -#include "common_j_h.c"
> +#include <errno.h>
> #include "numa_helper.h"
> -
> -char *TCID = "get_mempolicy01";
> -int TST_TOTAL = 1;
> -
> -#ifdef HAVE_NUMA_V2
> +#include "tst_numa.h"
> +#include "lapi/syscalls.h"
>
> #define MEM_LENGTH (4 * 1024 * 1024)
>
> -static int testno;
> +#define POLICY_DESC(x) .policy = x, .desc = "policy: "#x
> +#define POLICY_DESC_TEXT(x, y) .policy = x, .desc = "policy: "#x", "y
> +#define POLICY_DESC_FLAGS(x, y) .policy = x, .flags = y, .desc = "policy: "#x", flags: "#y
> +#define POLICY_DESC_FLAGS_TEXT(x, y, z) .policy = x, .flags = y, .desc = "policy: "#x", flags: "#y", "z
>
> -enum test_type {
> - DEFAULT, /* get default policy */
> - ADDR, /* get policy of memory which include mapped address */
> - INVALID_POINTER,
> - INVALID_FLAGS,
> -};
> +static struct bitmask *nodemask, *getnodemask, *empty_nodemask;
>
> -enum from_node {
> - NONE,
> - SELF,
> -};
> +static void test_set_mempolicy_default(unsigned int i);
> +static void test_set_mempolicy_none(unsigned int i);
> +static int test_mbind_none(unsigned int i);
> +static int test_mbind_default(unsigned int i);
> +static int set_invalid_addr(unsigned int i);
>
> struct test_case {
> - int ttype;
> int policy;
> - int from_node;
> + const char *desc;
> + unsigned int flags;
> int ret;
> int err;
> + char *addr;
> + int (*pre_test)(unsigned int i);
> + void (*test)(unsigned int i);
> + struct bitmask **exp_nodemask;
> };
>
> -/* Test cases
> - *
> - * test status of errors on man page
> - *
> - * (NONE) man page hadn't been completed.
> - *
> - * test status of errors NOT on man page
> - *
> - * EFAULT v (invalid address)
> - * EINVAL v (invalid parameters)
> - */
> static struct test_case tcase[] = {
> - { /* case00 */
> - .ttype = DEFAULT,
> - .policy = MPOL_DEFAULT,
> - .from_node = NONE,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case01 */
> - .ttype = DEFAULT,
> - .policy = MPOL_BIND,
> - .from_node = SELF,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case02 */
> - .ttype = DEFAULT,
> - .policy = MPOL_INTERLEAVE,
> - .from_node = SELF,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case03 */
> - .ttype = DEFAULT,
> - .policy = MPOL_PREFERRED,
> - .from_node = NONE,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case04 */
> - .ttype = DEFAULT,
> - .policy = MPOL_PREFERRED,
> - .from_node = SELF,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case05 */
> - .ttype = ADDR,
> - .policy = MPOL_DEFAULT,
> - .from_node = NONE,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case06 */
> - .ttype = ADDR,
> - .policy = MPOL_BIND,
> - .from_node = SELF,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case07 */
> - .ttype = ADDR,
> - .policy = MPOL_INTERLEAVE,
> - .from_node = SELF,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case08 */
> - .ttype = ADDR,
> - .policy = MPOL_PREFERRED,
> - .from_node = NONE,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case09 */
> - .ttype = ADDR,
> - .policy = MPOL_PREFERRED,
> - .from_node = SELF,
> - .ret = 0,
> - .err = 0,
> - },
> - { /* case10 */
> - .ttype = INVALID_POINTER,
> - .policy = MPOL_DEFAULT,
> - .from_node = NONE,
> - .ret = -1,
> - .err = EFAULT,
> - },
> - { /* case11 */
> - .ttype = INVALID_FLAGS,
> - .policy = MPOL_DEFAULT,
> - .from_node = NONE,
> - .ret = -1,
> - .err = EINVAL,
> - },
> + {
> + POLICY_DESC_TEXT(MPOL_DEFAULT, "no target"),
> + .ret = 0,
> + .err = 0,
> + .test = test_set_mempolicy_none,
> + .exp_nodemask = &empty_nodemask,
> + },
> + {
> + POLICY_DESC(MPOL_BIND),
> + .ret = 0,
> + .err = 0,
> + .test = test_set_mempolicy_default,
> + },
> + {
> + POLICY_DESC(MPOL_INTERLEAVE),
> + .ret = 0,
> + .err = 0,
> + .test = test_set_mempolicy_default,
> + .exp_nodemask = &nodemask,
> + },
> + {
> + POLICY_DESC_TEXT(MPOL_PREFERRED, "no target"),
> + .ret = 0,
> + .err = 0,
> + .test = test_set_mempolicy_none,
> + .exp_nodemask = &nodemask,
> + },
> + {
> + .test = test_set_mempolicy_default,
> + POLICY_DESC(MPOL_PREFERRED),
> + .ret = 0,
> + .err = 0,
> + },
> + {
> + POLICY_DESC_FLAGS_TEXT(MPOL_DEFAULT, MPOL_F_ADDR, "no target"),
> + .ret = 0,
> + .err = 0,
> + .pre_test = test_mbind_none,
> + .test = test_set_mempolicy_none,
> + .exp_nodemask = &nodemask,
> + },
> + {
> + POLICY_DESC_FLAGS(MPOL_BIND, MPOL_F_ADDR),
> + .pre_test = test_mbind_default,
> + .ret = 0,
> + .err = 0,
> + },
> + {
> + POLICY_DESC_FLAGS(MPOL_INTERLEAVE, MPOL_F_ADDR),
> + .ret = 0,
> + .err = 0,
> + .pre_test = test_mbind_default,
> + .test = test_set_mempolicy_default,
> + .exp_nodemask = &nodemask,
> + },
> + {
> + POLICY_DESC_FLAGS_TEXT(MPOL_PREFERRED, MPOL_F_ADDR, "no target"),
> + .ret = 0,
> + .err = 0,
> + .pre_test = test_mbind_none,
> + .test = test_set_mempolicy_none,
> + .exp_nodemask = &nodemask,
> + },
> + {
> + POLICY_DESC_FLAGS(MPOL_PREFERRED, MPOL_F_ADDR),
> + .ret = 0,
> + .err = 0,
> + .pre_test = test_mbind_default,
> + .test = test_set_mempolicy_default,
> + },
> + {
> + .flags = MPOL_F_ADDR,
> + POLICY_DESC_TEXT(MPOL_DEFAULT, "invalid address"),
> + .ret = -1,
> + .err = EFAULT,
> + .pre_test = set_invalid_addr,
> + .exp_nodemask = &nodemask,
> + },
> + {
> + POLICY_DESC_TEXT(MPOL_DEFAULT, "invalid flags, no target"),
> + .flags = -1,
> + .ret = -1,
> + .err = EINVAL,
> + .test = test_set_mempolicy_none,
> + .exp_nodemask = &nodemask,
> + },
> };
>
> -static int do_test(struct test_case *tc);
> -static void setup(void);
> -static void cleanup(void);
> +static void test_set_mempolicy_default(unsigned int i)
> +{
> + struct test_case *tc = &tcase[i];
> +
> + TEST(set_mempolicy(tc->policy, nodemask->maskp, nodemask->size));
> +}
>
> -int main(int argc, char **argv)
> +static void test_set_mempolicy_none(unsigned int i)
> {
> - int i, ret, lc;
> + struct test_case *tc = &tcase[i];
>
> - setup();
> + TEST(set_mempolicy(tc->policy, NULL, 0));
> +}
> +
> +static int test_mbind(unsigned int i, unsigned long *maskp, unsigned long size)
> +{
> + struct test_case *tc = &tcase[i];
>
> - ret = 0;
> - testno = (int)ARRAY_SIZE(tcase);
> - for (lc = 0; TEST_LOOPING(lc); lc++) {
> - tst_count = 0;
> + tc->addr = SAFE_MMAP(NULL, MEM_LENGTH, PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
>
> - for (i = 0; i < testno; i++) {
> - tst_resm(TINFO, "(case%02d) START", i);
> - ret = do_test(&tcase[i]);
> - tst_resm((ret == 0 ? TPASS : TFAIL | TERRNO),
> - "(case%02d) END", i);
> - }
> + TEST(mbind(tc->addr, MEM_LENGTH, tc->policy, maskp, size, 0));
> +
> + if (TST_RET < 0) {
> + tst_res(TFAIL | TERRNO, "mbind() failed");
> + return -1;
> }
>
> - cleanup();
> - tst_exit();
> + return 0;
> }
>
> -static int do_test(struct test_case *tc)
> +static int test_mbind_none(unsigned int i)
> {
> - int ret, err, result, cmp_ok;
> - int policy, flags;
> - struct bitmask *nodemask = numa_allocate_nodemask();
> - struct bitmask *getnodemask = numa_allocate_nodemask();
> - char *p = NULL;
> - unsigned long len = MEM_LENGTH;
> - int test_node = -1;
> + return test_mbind(i, NULL, 0);
> +}
>
> - ret = get_allowed_nodes(NH_MEMS, 1, &test_node);
> - if (ret < 0)
> - tst_brkm(TBROK | TERRNO, cleanup, "get_allowed_nodes: %d", ret);
> - numa_bitmask_setbit(nodemask, test_node);
> - switch (tc->ttype) {
> - case DEFAULT:
> - flags = 0;
> - p = NULL;
> - if (tc->from_node == NONE)
> - TEST(ltp_syscall(__NR_set_mempolicy, tc->policy,
> - NULL, 0));
> - else
> - TEST(ltp_syscall(__NR_set_mempolicy, tc->policy,
> - nodemask->maskp, nodemask->size));
> - if (TEST_RETURN < 0) {
> - tst_resm(TBROK | TERRNO, "set_mempolicy");
> - return -1;
> - }
> +static int test_mbind_default(unsigned int i)
> +{
> + return test_mbind(i, nodemask->maskp, nodemask->size);
> +}
>
> - break;
> - default:
> - flags = MPOL_F_ADDR;
> - p = mmap(NULL, len, PROT_READ | PROT_WRITE,
> - MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
> - if (p == MAP_FAILED)
> - tst_brkm(TBROK | TERRNO, cleanup, "mmap");
> - if (tc->from_node == NONE)
> - TEST(ltp_syscall(__NR_mbind, p, len, tc->policy,
> - NULL, 0, 0));
> - else
> - TEST(ltp_syscall(__NR_mbind, p, len, tc->policy,
> - nodemask->maskp, nodemask->size, 0));
> - if (TEST_RETURN < 0) {
> - tst_resm(TBROK | TERRNO, "mbind");
> - return -1;
> - }
> +static int set_invalid_addr(unsigned int i)
> +{
> + struct test_case *tc = &tcase[i];
> + int ret;
>
> - if (tc->ttype == INVALID_POINTER)
> -#ifdef __ia64__
> - p = (char *)0x8000000000000000UL;
> -#else
> - p = 0;
> -#endif
> + ret = test_mbind_none(i);
> + tc->addr = NULL;
>
> - if (tc->ttype == INVALID_FLAGS)
> - flags = -1;
> - }
> - errno = 0;
> - cmp_ok = 1;
> - TEST(ret = ltp_syscall(__NR_get_mempolicy, &policy, getnodemask->maskp,
> - getnodemask->size, p, flags));
> - err = TEST_ERRNO;
> - if (ret < 0)
> - goto TEST_END;
> -
> - /* if policy == MPOL_DEFAULT, get_mempolicy doesn't return nodemask */
> - if (tc->policy == MPOL_DEFAULT)
> - numa_bitmask_clearall(nodemask);
> - cmp_ok = (tc->policy == policy && (tc->from_node == NONE ||
> - numa_bitmask_equal(nodemask,
> - getnodemask)));
> -TEST_END:
> - result = (err != tc->err) || !cmp_ok;
> - PRINT_RESULT_CMP(0, tc->ret, tc->err, ret, err, cmp_ok);
> - return result;
> + return ret;
> }
>
> -static void cleanup(void)
> +
> +static void setup(void)
> {
> - tst_rmdir();
> + if (!is_numa(NULL, NH_MEMS, 1))
> + tst_brk(TCONF, "requires NUMA with at least 1 node");
> }
>
> -static void setup(void)
> +static void setup_node(void)
> {
> - /* check syscall availability */
> - ltp_syscall(__NR_get_mempolicy, NULL, NULL, 0, NULL, 0);
> + int test_node = -1;
>
> - if (!is_numa(NULL, NH_MEMS, 1))
> - tst_brkm(TCONF, NULL, "requires NUMA with at least 1 node");
> + if (get_allowed_nodes(NH_MEMS, 1, &test_node) < 0)
> + tst_brk(TBROK | TERRNO, "get_allowed_nodes failed");
The is_numa() and get_allowed_nodes() is deprecated API, we do have new
tst_get_nodemap() function that replaces them. See set_mempolicy()
testcases for reference.
> - TEST_PAUSE;
> - tst_tmpdir();
> + nodemask = numa_allocate_nodemask();
> + getnodemask = numa_allocate_nodemask();
> + numa_bitmask_setbit(nodemask, test_node);
> }
>
> -#else
> -int main(void)
> +static void do_test(unsigned int i)
> {
> - tst_brkm(TCONF, NULL, NUMA_ERROR_MSG);
> + struct test_case *tc = &tcase[i];
> + int policy;
> +
> + tst_res(TINFO, "test #%d: %s", (i+1), tc->desc);
> +
> + setup_node();
> +
> + if (tc->pre_test)
> + if (tc->pre_test(i) == -1)
> + return;
> +
> + if (tc->test) {
> + tc->test(i);
> +
> + if (TST_RET < 0) {
> + tst_res(TFAIL | TERRNO, ".test failed");
> + return;
> + }
> + }
We call test_mbind() here for each iteration which calls mmap()
and the memory is never freed. Which means that this will fail sooner or
later with the -i option.
Why can't we allocate all the blocks with different mempolicy and
or/bind the memory once in the test setup instead? We can keep the
callback in-place as they are we just need to loop over them in the
setup() instead. Also I would rename them to alloc, setup, or something
like that so that it's clear that they are just preparing the
environment and not doing the actuall test.
Also I would pass the struct test_case pointer to these instead of i
since they convert the i to the testcase pointer as the first thing
anyways.
--
Cyril Hrubis
chrubis@suse.cz
More information about the ltp
mailing list