All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cyril Hrubis <chrubis@suse.cz>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH 1/1] syscalls/get_mempolicy01: Rewrite to new API
Date: Wed, 9 Dec 2020 14:19:26 +0100	[thread overview]
Message-ID: <X9DO3uytgBaTrVwi@yuki.lan> (raw)
In-Reply-To: <20201208132814.16497-1-pvorel@suse.cz>

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

  parent reply	other threads:[~2020-12-09 13:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-08 13:28 [LTP] [PATCH 1/1] syscalls/get_mempolicy01: Rewrite to new API Petr Vorel
2020-12-08 13:54 ` Petr Vorel
2020-12-09 13:19 ` Cyril Hrubis [this message]
2020-12-09 22:10   ` Petr Vorel
2021-01-06 11:23   ` Petr Vorel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=X9DO3uytgBaTrVwi@yuki.lan \
    --to=chrubis@suse.cz \
    --cc=ltp@lists.linux.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.