From: Subrata M. <su...@li...> - 2008-07-11 19:40:01
|
Thanks Vijay for working hard to resend workouts in multiple cycles. I would test this on some real NUMA machine. I may be late in replying to you, but it will definitely get through. Meanwhile, would you also want to explore some ways to contribute to LTP ? Suzuki/Supriya, Would you like to review this. Regards-- Subrata A. On Sat, 2008-07-12 at 00:38 +0530, Vijay Kumar wrote: > Hi Subrata, > here is the updated patch with the following changes > > 1. Using get_mempolicy() to verify that the page is in the expected > NUMA node, as suggested by Andi Kleen. > > 2. Removed test case for mlocked pages, since mlocked pages can be > moved like any ordinary page. > > Signed-off-by: Vijay Kumar <vij...@br...> > > Index: ltp-mod/testcases/kernel/syscalls/move_pages/Makefile > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/Makefile 2008-07-10 08:18:39.000000000 +0530 > @@ -0,0 +1,46 @@ > +# > +# Copyright (c) International Business Machines Corp., 2001 > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > +# the GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +# > + > +CFLAGS += -I../../../../include -Wall > +LDLIBS += -L../../../../lib -lltp -lnuma -lrt > + > +ifeq ($(HAS_NUMA),yes) > +SRCS = $(wildcard *.c) > +TARGETS = $(patsubst %.c, %, $(wildcard *[0-9].c)) > +endif > + > +all: $(TARGETS) > + > +move_pages_support.o: move_pages_support.h move_pages_support.c > + > +$(TARGETS): move_pages_support.o > + > +install: move_page03.mode move_page11.mode > + @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done > + chmod 755 move_pages.sh; cp move_pages.sh ../../../bin/. > + > +clean: > + rm -f $(TARGETS) > + > +move_page03.mode: > + @/bin/sh ./move_pages03.mode.sh > + > +move_page11.mode: > + @/bin/sh ./move_pages11.mode.sh > + > +.PHONY: move_pages03.mode > \ No newline at end of file > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages01.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages01.c 2008-07-09 23:20:23.000000000 +0530 > @@ -0,0 +1,151 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages01.c > + * > + * DESCRIPTION > + * Test retrieval of NUMA node > + * > + * ALGORITHM > + * 1. Allocate pages in NUMA nodes A and B. > + * 2. Use move_pages() to retrieve the NUMA node of the pages. > + * 3. Check if the NUMA nodes reported are correct. > + * > + * USAGE: <for command-line> > + * move_pages01 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/signal.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define TEST_PAGES 2 > +#define TEST_NODES TEST_PAGES > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages01"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +int main(int argc, char **argv) > +{ > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[TEST_PAGES] = { 0 }; > + int status[TEST_PAGES]; > + int ret; > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_pages_linear(pages, TEST_PAGES); > + if (ret == -1) > + continue; > + > + ret = numa_move_pages(0, TEST_PAGES, pages, NULL, status, 0); > + TEST_ERRNO = errno; > + if (ret != 0) { > + tst_resm(TFAIL, "retrieving NUMA nodes failed"); > + free_pages(pages, TEST_PAGES); > + continue; > + } > + > + verify_pages_linear(pages, status, TEST_PAGES); > + > + free_pages(pages, TEST_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(NOFORK, DEF_HANDLER, cleanup); > + > + check_config(TEST_NODES); > + /* Pause if that option was specified > + * TEST_PAUSE contains the code to fork the test with the -c option. > + */ > + TEST_PAUSE; > +} > + > +/* > + * cleanup() - performs all ONE TIME cleanup for this test > + */ > +void > +cleanup(void) > +{ > + /* > + * print timing stats if that option was specified. > + * print errno log if that option was specified. > + */ > + TEST_CLEANUP; > + > + /* exit with return code appropriate for results */ > + tst_exit(); > + /*NOTREACHED*/ > +} > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages02.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages02.c 2008-07-09 23:20:23.000000000 +0530 > @@ -0,0 +1,163 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages02.c > + * > + * DESCRIPTION > + * Test movement of pages mapped by a process. > + * > + * ALGORITHM > + * 1. Allocate pages in NUMA node A. > + * 2. Use move_pages() to move the pages to NUMA node B. > + * 3. Retrieve the NUMA nodes of the moved pages. > + * 4. Check if all pages are in node B. > + * > + * USAGE: <for command-line> > + * move_pages02 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/signal.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define TEST_PAGES 2 > +#define TEST_NODES 2 > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages02"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +int main(int argc, char **argv) > +{ > + unsigned int i; > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + unsigned int from_node = 0; > + unsigned int to_node = 1; > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[TEST_PAGES] = { 0 }; > + int nodes[TEST_PAGES]; > + int status[TEST_PAGES]; > + int ret; > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_pages_on_node(pages, TEST_PAGES, from_node); > + if (ret == -1) > + continue; > + > + for (i = 0; i < TEST_PAGES; i++) > + nodes[i] = to_node; > + > + ret = numa_move_pages(0, TEST_PAGES, pages, nodes, status, MPOL_MF_MOVE); > + TEST_ERRNO = errno; > + if (ret != 0) { > + tst_resm(TFAIL, "retrieving NUMA nodes failed"); > + free_pages(pages, TEST_PAGES); > + continue; > + } > + > + for (i = 0; i < TEST_PAGES; i++) > + *((char *)pages[i]) = 0xAA; > + > + verify_pages_on_node(pages, status, TEST_PAGES, to_node); > + > + free_pages(pages, TEST_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(NOFORK, DEF_HANDLER, cleanup); > + > + check_config(TEST_NODES); > + > + /* Pause if that option was specified > + * TEST_PAUSE contains the code to fork the test with the -c option. > + */ > + TEST_PAUSE; > +} > + > +/* > + * cleanup() - performs all ONE TIME cleanup for this test at completion > + */ > +void > +cleanup(void) > +{ > + /* > + * print timing stats if that option was specified. > + * print errno log if that option was specified. > + */ > + TEST_CLEANUP; > + > + /* exit with return code appropriate for results */ > + tst_exit(); > + /*NOTREACHED*/ > +} > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages03.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages03.c 2008-07-09 23:20:23.000000000 +0530 > @@ -0,0 +1,237 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages03.c > + * > + * DESCRIPTION > + * Test movement of pages mapped by a process. > + * > + * ALGORITHM > + * 1. Start the test case program as root. > + * 2. Allocate a shared memory in NUMA node A. > + * 3. Fork another process. > + * 4. Use move_pages() to move the pages to NUMA node B, with the > + * MPOL_MF_MOVE_ALL. > + * 5. Check if all pages are in node B. > + * > + * USAGE: <for command-line> > + * move_pages03 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <unistd.h> > +#include <signal.h> > +#include <semaphore.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define TEST_PAGES 2 > +#define TEST_NODES 2 > + > +enum { > + SEM_CHILD_SETUP, > + SEM_PARENT_TEST, > + > + MAX_SEMS > +}; > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages03"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +/* > + * child() - touches shared pages, and waits for signal from parent. > + * @pages: shared pages allocated in parent > + * @sem: semaphore to sync with parent > + */ > +void > +child(void **pages, sem_t *sem) > +{ > + int i; > + > + for (i = 0; i < TEST_PAGES; i++) { > + char *page; > + > + page = pages[i]; > + page[0] = 0xAA; > + } > + > + /* Setup complete. Ask parent to continue. */ > + if (sem_post(&sem[SEM_CHILD_SETUP]) == -1) > + tst_resm(TWARN, "error post semaphore: %s", strerror(errno)); > + > + /* Wait for testcase in parent to complete. */ > + if (sem_wait(&sem[SEM_PARENT_TEST]) == -1) > + tst_resm(TWARN, "error wait semaphore: %s", strerror(errno)); > + > + exit(0); > +} > + > +int main(int argc, char **argv) > +{ > + unsigned int i; > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + unsigned int from_node = 0; > + unsigned int to_node = 1; > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[TEST_PAGES] = { 0 }; > + int nodes[TEST_PAGES]; > + int status[TEST_PAGES]; > + int ret; > + pid_t cpid; > + sem_t *sem; > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_shared_pages_on_node(pages, TEST_PAGES, > + from_node); > + if (ret == -1) > + continue; > + > + > + for (i = 0; i < TEST_PAGES; i++) { > + nodes[i] = to_node; > + } > + > + sem = alloc_sem(MAX_SEMS); > + if (sem == NULL) { > + goto err_free_pages; > + } > + > + /* > + * Fork a child process so that the shared pages are > + * now really shared between two processes. > + */ > + cpid = fork(); > + if (cpid == -1) { > + tst_resm(TBROK, "forking child failed: %s", > + strerror(errno)); > + goto err_free_sem; > + } else if (cpid == 0) { > + child(pages, sem); > + } > + > + /* Wait for child to setup and signal. */ > + if (sem_wait(&sem[SEM_CHILD_SETUP]) == -1) > + tst_resm(TWARN, "error wait semaphore: %s", > + strerror(errno)); > + > + ret = numa_move_pages(0, TEST_PAGES, pages, nodes, > + status, MPOL_MF_MOVE_ALL); > + TEST_ERRNO = errno; > + if (ret != 0) { > + tst_resm(TFAIL, "retrieving NUMA nodes failed"); > + goto err_kill_child; > + } > + > + verify_pages_on_node(pages, status, TEST_PAGES, to_node); > + > + err_kill_child: > + /* Test done. Ask child to terminate. */ > + if (sem_post(&sem[SEM_PARENT_TEST]) == -1) > + tst_resm(TWARN, "error post semaphore: %s", > + strerror(errno)); > + /* Read the status, no zombies! */ > + wait(NULL); > + err_free_sem: > + free_sem(sem, MAX_SEMS); > + err_free_pages: > + free_shared_pages(pages, TEST_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + check_config(TEST_NODES); > + > + /* Pause if that option was specified > + * TEST_PAUSE contains the code to fork the test with the -c option. > + */ > + TEST_PAUSE; > +} > + > +/* > + * cleanup() - performs all ONE TIME cleanup for this test at completion > + */ > +void > +cleanup(void) > +{ > + /* > + * print timing stats if that option was specified. > + * print errno log if that option was specified. > + */ > + TEST_CLEANUP; > + > + /* exit with return code appropriate for results */ > + tst_exit(); > + /*NOTREACHED*/ > +} > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages_support.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages_support.c 2008-07-09 23:20:23.000000000 +0530 > @@ -0,0 +1,429 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#include <sys/mman.h> > +#include <syscall.h> > +#include <unistd.h> > +#include <semaphore.h> > +#include <numa.h> > +#include <numaif.h> > +#include <errno.h> > + > +#include <test.h> > +#include <usctest.h> > +#include <linux_syscall_numbers.h> > + > +#include "move_pages_support.h" > + > +#ifndef __NR_move_pages > + int arch_support = 0; > +#else > + int arch_support = 1; > +#endif > + > +long > +get_page_size() > +{ > + return sysconf(_SC_PAGESIZE); > +} > + > +/* > + * free_pages() - free an array of pages > + * @pages: array of page pointers to be freed > + * @num: no. of pages in the array > + */ > +void > +free_pages(void **pages, unsigned int num) > +{ > + int i; > + size_t onepage = get_page_size(); > + > + for (i = 0; i < num; i++) { > + if (pages[i] != NULL) { > + numa_free(pages[i], onepage); > + } > + } > +} > + > +/* > + * alloc_pages_on_nodes() - allocate pages on specified NUMA nodes > + * @pages: array in which the page pointers will be stored > + * @num: no. of pages to allocate > + * @nodes: array of NUMA nodes > + * > + * A page will be allocated in each node specified by @nodes, and the > + * page pointers will be stored in @pages array. > + * > + * RETURNS: > + * 0 on success, -1 on allocation failure. > + */ > +int > +alloc_pages_on_nodes(void **pages, unsigned int num, int *nodes) > +{ > + int i; > + size_t onepage = get_page_size(); > + > + for (i = 0; i < num; i++) { > + pages[i] = NULL; > + } > + > + for (i = 0; i < num; i++) { > + char *page; > + > + pages[i] = numa_alloc_onnode(onepage, nodes[i]); > + if (pages[i] == NULL) { > + tst_resm(TBROK, "allocation of page on node " > + "%d failed", nodes[i]); > + break; > + } > + > + /* Touch the page, to force allocation. */ > + page = pages[i]; > + page[0] = i; > + } > + > + if (i == num) > + return 0; > + > + free_pages(pages, num); > + > + return -1; > +} > + > +/* > + * alloc_pages_linear() - allocate pages in each NUMA node > + * @pages: array in which the page pointers will be stored > + * @num: no. of pages to allocate > + * > + * Pages will be allocated one from each NUMA node, in an interleaved > + * fashion. > + * > + * RETURNS: > + * 0 on success, -1 on allocation failure. > + */ > +int > +alloc_pages_linear(void **pages, unsigned int num) > +{ > + unsigned int i; > + unsigned int n; > + int nodes[num]; > + > + n = 0; > + for (i = 0; i < num; i++) { > + nodes[i] = n; > + > + n++; > + if (n > numa_max_node()) > + n = 0; > + } > + > + return alloc_pages_on_nodes(pages, num, nodes); > +} > + > +/* > + * alloc_pages_on_node() - allocate pages on specified NUMA node > + * @pages: array in which the page pointers will be stored > + * @num: no. of pages to allocate > + * @node: NUMA node from which to allocate pages > + * > + * Pages will be allocated from the NUMA node @node, and the page > + * pointers will be stored in the @pages array. > + * > + * RETURNS: > + * 0 on success, -1 on allocation failure. > + */ > +int > +alloc_pages_on_node(void **pages, unsigned int num, int node) > +{ > + unsigned int i; > + int nodes[num]; > + > + for (i = 0; i < num; i++) > + nodes[i] = node; > + > + return alloc_pages_on_nodes(pages, num, nodes); > +} > + > +void > +print_bitmask(struct bitmask *bm) > +{ > + int i; > + int nbytes = bm->size / sizeof(*bm->maskp); > + > + printf("%d: ", nbytes); > + for (i = 0; i < nbytes; i++) > + printf("0x%lx ", bm->maskp[i]); > + > + printf("\n"); > +} > + > +/* > + * verify_pages_on_nodes() - verify pages are in specified nodes > + * @pages: array of pages to be verified > + * @status: the NUMA node of each page > + * @num: the no. of pages > + * @nodes: the expected NUMA nodes > + */ > +void > +verify_pages_on_nodes(void **pages, int *status, unsigned int num, int *nodes) > +{ > + unsigned int i; > + int which_node; > + int ret; > + > + for (i = 0; i < num; i++) { > + if (status[i] != nodes[i]) { > + tst_resm(TFAIL, "page %d on node %d, " > + "expected on node %p", i, > + status[i], nodes[i]); > + return; > + } > + > + /* Based on inputs from Andi Kleen. > + * > + * Retrieves numa node for the given page. This does > + * not seem to be documented in the man pages. > + */ > + ret = get_mempolicy(&which_node, NULL, 0, > + pages[i], > + MPOL_F_NODE | MPOL_F_ADDR); > + if (ret == -1) { > + tst_resm(TBROK, "error getting memory policy for " > + "page %p: %s", pages[i], strerror(errno)); > + return; > + } > + > + if (which_node != nodes[i]) { > + tst_resm(TFAIL, "page %p is not in node %d ", > + pages[i], nodes[i]); > + return; > + } > + } > + > + tst_resm(TPASS, "pages are present in expected nodes"); > +} > + > +/* > + * verify_pages_linear() - verify pages are interleaved > + * @pages: array of pages to be verified > + * @status: the NUMA node of each page > + * @num: the no. of pages > + */ > +void > +verify_pages_linear(void **pages, int *status, unsigned int num) > +{ > + unsigned int i; > + unsigned int n; > + int nodes[num]; > + > + n = 0; > + for (i = 0; i < num; i++) { > + nodes[i] = i; > + > + n++; > + if (n > numa_max_node()) > + n = 0; > + } > + > + verify_pages_on_nodes(pages, status, num, nodes); > +} > + > +/* > + * verify_pages_on_node() - verify pages are in specified node > + * @pages: array of pages to be verified > + * @status: the NUMA node of each page > + * @num: the no. of pages > + * @node: the expected NUMA node > + */ > +void > +verify_pages_on_node(void **pages, int *status, unsigned int num, int node) > +{ > + unsigned int i; > + int nodes[num]; > + > + for (i = 0; i < num; i++) { > + nodes[i] = node; > + } > + > + verify_pages_on_nodes(pages, status, num, nodes); > +} > + > +/* > + * alloc_shared_pages_on_node() - allocate shared pages on a NUMA node > + * @pages: array to store the allocated pages > + * @num: the no. of pages to allocate > + * @node: the node in which the pages should be allocated > + * > + * RETURNS: > + * 0 on success, -1 on allocation failure > + */ > +int > +alloc_shared_pages_on_node(void **pages, unsigned int num, > + int node) > +{ > + char *shared; > + unsigned int i; > + int nodes[num]; > + size_t total_size = num * get_page_size(); > + > + shared = mmap(NULL, total_size, > + PROT_READ | PROT_WRITE, > + MAP_SHARED | MAP_ANONYMOUS, 0, 0); > + if (shared == MAP_FAILED) { > + tst_resm(TBROK, "allocation of shared pages failed: %s", > + strerror(errno)); > + return -1; > + } > + > + numa_tonode_memory(shared, total_size, node); > + > + for (i = 0; i < num; i++) { > + char *page; > + > + pages[i] = shared; > + shared += get_page_size(); > + > + nodes[i] = node; > + > + /* Touch the page to force allocation */ > + page = pages[i]; > + page[0] = i; > + } > + > + return 0; > +} > + > +/* > + * free_shared_pages() - free shared pages > + * @pages: array of pages to be freed > + * @num: the no. of pages to free > + */ > +void > +free_shared_pages(void **pages, unsigned int num) > +{ > + int ret; > + > + ret = munmap(pages[0], num * get_page_size()); > + if (ret == -1) > + tst_resm(TWARN, "unmapping of shared pages failed: %s", > + strerror(errno)); > +} > + > +/* > + * alloc_sem() - allocate semaphores > + * @num - no. of semaphores to create > + * > + * Allocate and initialize semaphores in a shared memory area, so that > + * the semaphore can be used accross processes. > + * > + * RETURNS: > + * Array of initialized semaphores. > + */ > +sem_t * > +alloc_sem(int num) > +{ > + sem_t *sem; > + void *sem_mem; > + int i, ret; > + > + sem_mem = mmap(NULL, get_page_size(), > + PROT_READ | PROT_WRITE, > + MAP_SHARED | MAP_ANONYMOUS, 0, 0); > + if (sem_mem == MAP_FAILED) { > + tst_resm(TBROK, "allocation of semaphore page failed: %s", > + strerror(errno)); > + goto err_exit; > + } > + > + sem = sem_mem; > + > + for (i = 0; i < num; i++) { > + ret = sem_init(&sem[i], 1, 0); > + if (ret == -1) { > + tst_resm(TBROK, "semaphore initialization failed: %s", > + strerror(errno)); > + goto err_free_mem; > + } > + } > + > + return sem; > + > + err_free_mem: > + ret = munmap(sem_mem, get_page_size()); > + if (ret == -1) > + tst_resm(TWARN, "error freeing semaphore memory: %s", > + strerror(errno)); > + err_exit: > + return NULL; > +} > + > +/* > + * free_sem() - free semaphores > + * @sem - array of semphores to be freed > + * @num - no. of semaphores in the array > + */ > +void > +free_sem(sem_t *sem, int num) > +{ > + int i; > + int ret; > + > + for (i = 0; i < num; i++) { > + ret = sem_destroy(&sem[i]); > + if (ret == -1) > + tst_resm(TWARN, "error destroying semaphore: %s", > + strerror(errno)); > + } > + > + ret = munmap(sem, get_page_size()); > + if (ret == -1) > + tst_resm(TWARN, "error freeing semaphore memory: %s", > + strerror(errno)); > +} > + > +/* > + * check_config() - check for required configuration > + * @min_nodes: the minimum required NUMA nodes > + * > + * Checks if numa support is availabe, kernel is >= 2.6.18, arch is > + * one of the supported architectures. > + */ > +void > +check_config(unsigned int min_nodes) > +{ > + if (numa_available() < 0) { > + tst_resm(TCONF, "NUMA support is not available"); > + tst_exit(); > + } > + > + if (numa_max_node() < (min_nodes - 1)) { > + tst_resm(TCONF, "atleast 2 NUMA nodes are required"); > + tst_exit(); > + } > + > + if (tst_kvercmp(2, 6, 18) < 0) { > + tst_resm(TCONF, "2.6.18 or greater kernel required"); > + tst_exit(); > + } > + > + if (arch_support == 0) { > + tst_resm(TCONF, "this arch does not support move_pages"); > + tst_exit(); > + } > +} > + > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages_support.h > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages_support.h 2008-07-09 23:20:23.000000000 +0530 > @@ -0,0 +1,47 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#ifndef MOVE_PAGES_SUPPORT_H > +#define MOVE_PAGES_SUPPORT_H > + > +#include <numaif.h> > +#include <semaphore.h> > + > +long get_page_size(); > + > +void free_pages(void **pages, unsigned int num); > + > +int alloc_pages_on_nodes(void **pages, unsigned int num, int *nodes); > +int alloc_pages_linear(void **pages, unsigned int num); > +int alloc_pages_on_node(void **pages, unsigned int num, int node); > + > +void verify_pages_on_nodes(void **pages, int *status, > + unsigned int num, int *nodes); > +void verify_pages_linear(void **pages, int *status, unsigned int num); > +void verify_pages_on_node(void **pages, int *status, > + unsigned int num, int node); > + > +int alloc_shared_pages_on_node(void **pages, unsigned int num, int node); > +void free_shared_pages(void **pages, unsigned int num); > + > +sem_t *alloc_sem(int num); > +void free_sem(sem_t *sem, int num); > + > +void check_config(unsigned int min_nodes); > + > +#endif > Index: ltp-mod/runtest/numa > =================================================================== > --- ltp-mod.orig/runtest/numa 2008-06-29 09:54:54.000000000 +0530 > +++ ltp-mod/runtest/numa 2008-07-10 08:24:48.000000000 +0530 > @@ -1 +1,14 @@ > Numa-testcases numa01.sh > +move_pages01 move_pages.sh 01 > +move_pages02 move_pages.sh 02 > +move_pages03 move_pages.sh 03 > +move_pages04 move_pages.sh 04 > +move_pages05 move_pages.sh 05 > +move_pages06 move_pages.sh 06 > +move_pages07 move_pages.sh 07 > +move_pages08 move_pages.sh 08 > +move_pages09 move_pages.sh 09 > +move_pages10 move_pages.sh 10 > +move_pages11 move_pages.sh 11 > + > + > Index: ltp-mod/runtest/syscalls > =================================================================== > --- ltp-mod.orig/runtest/syscalls 2008-06-29 09:55:58.000000000 +0530 > +++ ltp-mod/runtest/syscalls 2008-07-10 08:25:01.000000000 +0530 > @@ -445,6 +445,18 @@ > #mount03 mount03 -D /dev/... > #mount04 mount04 -D /dev/... > > +move_pages01 move_pages.sh 01 > +move_pages02 move_pages.sh 02 > +move_pages03 move_pages.sh 03 > +move_pages04 move_pages.sh 04 > +move_pages05 move_pages.sh 05 > +move_pages06 move_pages.sh 06 > +move_pages07 move_pages.sh 07 > +move_pages08 move_pages.sh 08 > +move_pages09 move_pages.sh 09 > +move_pages10 move_pages.sh 10 > +move_pages11 move_pages.sh 11 > + > mprotect01 mprotect01 > mprotect02 mprotect02 > mprotect03 mprotect03 > Index: ltp-mod/Makefile > =================================================================== > --- ltp-mod.orig/Makefile 2008-06-29 09:54:54.000000000 +0530 > +++ ltp-mod/Makefile 2008-06-29 09:56:02.000000000 +0530 > @@ -37,8 +37,10 @@ > RANLIB=$(CROSS_COMPILER)ranlib > endif > > +HAS_NUMA=$(shell sh tools/scripts/numa_test.sh) > + > export CFLAGS += -Wall $(CROSS_CFLAGS) > -export CC AR RANLIB LDFLAGS > +export CC AR RANLIB LDFLAGS HAS_NUMA > > -include config.mk > > Index: ltp-mod/testcases/kernel/numa/Makefile > =================================================================== > --- ltp-mod.orig/testcases/kernel/numa/Makefile 2008-06-29 09:54:54.000000000 +0530 > +++ ltp-mod/testcases/kernel/numa/Makefile 2008-06-29 09:56:02.000000000 +0530 > @@ -20,7 +20,7 @@ > > LDLIBS += -L../../../lib -lltp > > -ifeq ($(shell sh test.sh),yes) #its a numa machine > +ifeq ($(HAS_NUMA),yes) #its a numa machine > LDLIBS += -L../../../lib -lnuma > SRCS = $(wildcard *.c) > TARGETS = $(patsubst %.c,%,$(SRCS)) > Index: ltp-mod/testcases/kernel/numa/test.sh > =================================================================== > --- ltp-mod.orig/testcases/kernel/numa/test.sh 2008-06-29 09:54:54.000000000 +0530 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,53 +0,0 @@ > -################################################################################ > -## ## > -## Copyright (c) International Business Machines Corp., 2007 ## > -## ## > -## This program is free software; you can redistribute it and#or modify ## > -## it under the terms of the GNU General Public License as published by ## > -## the Free Software Foundation; either version 2 of the License, or ## > -## (at your option) any later version. ## > -## ## > -## This program is distributed in the hope that it will be useful, but ## > -## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ## > -## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ## > -## for more details. ## > -## ## > -## You should have received a copy of the GNU General Public License ## > -## along with this program; if not, write to the Free Software ## > -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## > -## ## > -################################################################################ > -# > -# Author Pradeep Kumar Surisetty, pra...@in... > -# > -# History Nov 27 2007 -created- pradeep kumar surisetty > -#! /bin/sh > -# > -# File : test.sh > - > - > -#!/bin/sh > -x=0 > -chk_ifexist() > -{ > -if [ ! -d /sys/devices/system/node ] > -then > -x=0 > -else > -x=$(ls /sys/devices/system/node | wc -l) > -fi > -if [ $x -gt 1 ] > -then > - if [ ! -f /usr/include/numa.h ] > - then > - echo no; > - else > - echo yes; > - fi > -else > - echo no; #numa is not present > - > -fi > -} > -chk_ifexist > - > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages03.mode.sh > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages03.mode.sh 2008-06-29 09:56:02.000000000 +0530 > @@ -0,0 +1,18 @@ > +#!/bin/sh > + > +failed() { > + echo "" > + echo " ************** WARNING **************" > + echo " Cannot change permission or ownership of \"move_pages03\"." > + echo " Test move_pages03 will fail" > + echo " Run "make install" as root." > + echo " *************************************" > + sleep 2 > +} > + > +if [ -f move_pages03 ]; then > + chown root move_pages03 || failed > + chmod 04755 move_pages03 || failed > +fi > + > +exit 0 > Index: ltp-mod/tools/scripts/numa_test.sh > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/tools/scripts/numa_test.sh 2008-06-29 09:56:02.000000000 +0530 > @@ -0,0 +1,53 @@ > +############################################################################# > +## > +## Copyright (c) International Business Machines Corp., 2007 > +## > +## This program is free software; you can redistribute it and#or modify > +## it under the terms of the GNU General Public License as published by > +## the Free Software Foundation; either version 2 of the License, or > +## (at your option) any later version. > +## > +## This program is distributed in the hope that it will be useful, but > +## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY > +## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +## for more details. > +## > +## You should have received a copy of the GNU General Public License > +## along with this program; if not, write to the Free Software > +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > +## > +############################################################################# > +# > +# Author Pradeep Kumar Surisetty, pra...@in... > +# > +# History Nov 27 2007 -created- pradeep kumar surisetty > +#! /bin/sh > +# > +# File : numa_test.sh > + > + > +#!/bin/sh > +x=0 > +chk_ifexist() > +{ > +if [ ! -d /sys/devices/system/node ] > +then > +x=0 > +else > +x=$(ls /sys/devices/system/node | wc -l) > +fi > +if [ $x -gt 1 ] > +then > + if [ ! -f /usr/include/numa.h ] > + then > + echo no; > + else > + echo yes; > + fi > +else > + echo no; #numa is not present > + > +fi > +} > +chk_ifexist > + > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages.sh > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages.sh 2008-06-29 21:42:37.000000000 +0530 > @@ -0,0 +1,18 @@ > +#!/bin/sh > + > +if [ -z "$1" ]; then > + echo "Usage: move_pages.sh <test-number>" > + exit 1 > +fi > + > +testprog=move_pages${1} > + > +shopt -s execfail > +exec $testprog > + > +export TCID=$testprog > +export TST_TOTAL=1 > +export TST_COUNT=0 > +tst_resm TCONF "libnuma and NUMA support is required for this testcase" > + > +tst_exit > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages04.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages04.c 2008-06-29 22:04:41.000000000 +0530 > @@ -0,0 +1,185 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages04.c > + * > + * DESCRIPTION > + * Failure when page does not exit. > + * > + * ALGORITHM > + * > + * 1. Pass a page that does not exit as one of the page addresses > + * to move_pages(). > + * 2. Check if the corresponding status is set to -ENOENT. > + * > + * USAGE: <for command-line> > + * move_pages04 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/mman.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <unistd.h> > +#include <signal.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define TEST_PAGES 2 > +#define TEST_NODES 2 > +#define TOUCHED_PAGES 1 > +#define UNTOUCHED_PAGE (TEST_PAGES - 1) > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages04"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +typedef void (*sighandler_t)(int); > + > +int main(int argc, char **argv) > +{ > + unsigned int i; > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + unsigned int from_node = 0; > + unsigned int to_node = 1; > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[TEST_PAGES] = { 0 }; > + int nodes[TEST_PAGES]; > + int status[TEST_PAGES]; > + int ret; > + unsigned long onepage = get_page_size(); > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_pages_on_node(pages, TOUCHED_PAGES, from_node); > + if (ret == -1) > + continue; > + > + /* Allocate page and do not touch it. */ > + pages[UNTOUCHED_PAGE] = numa_alloc_onnode(onepage, from_node); > + if (pages[UNTOUCHED_PAGE] == NULL) { > + tst_resm(TBROK, "failed allocating page on node %d", > + from_node); > + goto err_free_pages; > + } > + > + for (i = 0; i < TEST_PAGES; i++) > + nodes[i] = to_node; > + > + ret = numa_move_pages(0, TEST_PAGES, pages, nodes, > + status, MPOL_MF_MOVE); > + TEST_ERRNO = errno; > + if (ret == -1) { > + tst_resm(TFAIL, "move_pages unexpectedly failed: %s", > + strerror(errno)); > + goto err_free_pages; > + } > + > + if (status[UNTOUCHED_PAGE] == -ENOENT) > + tst_resm(TPASS, "status[%d] set to expected -ENOENT", > + UNTOUCHED_PAGE); > + else > + tst_resm(TFAIL, "status[%d] is %d", UNTOUCHED_PAGE, > + status[UNTOUCHED_PAGE]); > + > + err_free_pages: > + /* This is capable of freeing both the touched and > + * untouched pages. > + */ > + free_pages(pages, TEST_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + check_config(TEST_NODES); > + > + /* Pause if that option was specified > + * TEST_PAUSE contains the code to fork the test with the -c option. > + */ > + TEST_PAUSE; > +} > + > +/* > + * cleanup() - performs all ONE TIME cleanup for this test at completion > + */ > +void > +cleanup(void) > +{ > + /* > + * print timing stats if that option was specified. > + * print errno log if that option was specified. > + */ > + TEST_CLEANUP; > + > + /* exit with return code appropriate for results */ > + tst_exit(); > + /*NOTREACHED*/ > +} > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages05.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages05.c 2008-06-29 22:04:41.000000000 +0530 > @@ -0,0 +1,250 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages05.c > + * > + * DESCRIPTION > + * Test movement of pages mapped by a process. > + * > + * ALGORITHM > + * 1. Start the test case program as root. > + * 2. Allocate a shared memory in NUMA node A. > + * 3. Fork another process. > + * 4. Use move_pages() to move the pages to NUMA node B, without > + * the MPOL_MF_MOVE_ALL. > + * 5. Check if the corresponding status is set to -EACCES. > + * > + * USAGE: <for command-line> > + * move_pages05 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <unistd.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define SHARED_PAGE 0 > +#define N_SHARED_PAGES 1 > +#define UNSHARED_PAGE 1 > +#define N_UNSHARED_PAGES 1 > +#define N_TEST_PAGES (N_SHARED_PAGES + N_UNSHARED_PAGES) > +#define N_TEST_NODES 2 > + > +enum { > + SEM_CHILD_SETUP, > + SEM_PARENT_TEST, > + > + MAX_SEMS > +}; > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages05"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +/* > + * child() - touches pages, and waits for signal from parent. > + * @pages: shared pages allocated in parent > + */ > +void child(void **pages, sem_t *sem) > +{ > + int i; > + > + for (i = 0; i < N_TEST_PAGES; i++) { > + char *page; > + > + page = pages[i]; > + page[0] = 0xAA; > + } > + > + /* Setup complete. Ask parent to continue. */ > + if (sem_post(&sem[SEM_CHILD_SETUP]) == -1) > + tst_resm(TWARN, "error post semaphore: %s", strerror(errno)); > + > + /* Wait for testcase in parent to complete. */ > + if (sem_wait(&sem[SEM_PARENT_TEST]) == -1) > + tst_resm(TWARN, "error wait semaphore: %s", strerror(errno)); > + > + exit(0); > +} > + > +int main(int argc, char **argv) > +{ > + unsigned int i; > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + unsigned int from_node = 0; > + unsigned int to_node = 1; > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[N_TEST_PAGES] = { 0 }; > + int nodes[N_TEST_PAGES]; > + int status[N_TEST_PAGES]; > + int ret; > + pid_t cpid; > + sem_t *sem; > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_shared_pages_on_node(pages + SHARED_PAGE, > + N_SHARED_PAGES, > + from_node); > + if (ret == -1) > + continue; > + > + ret = alloc_pages_on_node(pages + UNSHARED_PAGE, > + N_UNSHARED_PAGES, > + from_node); > + if (ret == -1) > + goto err_free_shared; > + > + for (i = 0; i < N_TEST_PAGES; i++) { > + nodes[i] = to_node; > + } > + > + sem = alloc_sem(MAX_SEMS); > + if (sem == NULL) { > + goto err_free_unshared; > + } > + > + /* > + * Fork a child process so that the shared pages are > + * now really shared between two processes. > + */ > + cpid = fork(); > + if (cpid == -1) { > + tst_resm(TBROK, "forking child failed"); > + goto err_free_sem; > + } else if (cpid == 0) { > + child(pages, sem); > + } > + > + /* Wait for child to setup and signal. */ > + if (sem_wait(&sem[SEM_CHILD_SETUP]) == -1) > + tst_resm(TWARN, "error wait semaphore: %s", > + strerror(errno)); > + > + ret = numa_move_pages(0, N_TEST_PAGES, pages, nodes, > + status, MPOL_MF_MOVE); > + TEST_ERRNO = errno; > + if (ret == -1) { > + tst_resm(TFAIL, "move_pages unexpectedly failed: %s", > + strerror(errno)); > + goto err_kill_child; > + } > + > + if (status[SHARED_PAGE] == -EACCES) > + tst_resm(TPASS, "status[%d] set to expected -EACCES", > + SHARED_PAGE); > + else > + tst_resm(TFAIL, "status[%d] is %d", > + SHARED_PAGE, status[SHARED_PAGE]); > + > + err_kill_child: > + /* Test done. Ask child to terminate. */ > + if (sem_post(&sem[SEM_PARENT_TEST]) == -1) > + tst_resm(TWARN, "error post semaphore: %s", > + strerror(errno)); > + /* Read the status, no zombies! */ > + wait(NULL); > + err_free_sem: > + free_sem(sem, MAX_SEMS); > + err_free_unshared: > + free_pages(pages + UNSHARED_PAGE, N_UNSHARED_PAGES); > + err_free_shared: > + free_shared_pages(pages + SHARED_PAGE, N_SHARED_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + check_config(N_TEST_NODES); > + > + /* Pause if that option was specified > + * TEST_PAUSE contains the code to fork the test with the -c option. > + */ > + TEST_PAUSE; > +} > + > +/* > + * cleanup() - performs all ONE TIME cleanup for this test at completion > + */ > +void > +cleanup(void) > +{ > + /* > + * print timing stats if that option was specified. > + * print errno log if that option was specified. > + */ > + TEST_CLEANUP; > + > + /* exit with return code appropriate for results */ > + tst_exit(); > + /*NOTREACHED*/ > +} > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages06.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages06.c 2008-07-10 08:19:08.000000000 +0530 > @@ -0,0 +1,161 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages06.c > + * > + * DESCRIPTION > + * Failure when NUMA node is invalid. > + * > + * ALGORITHM > + * > + * 1. Pass a non-existent NUMA node number to move_pages(). > + * 2. Check if errno is set to ENODEV. > + * > + * USAGE: <for command-line> > + * move_pages06 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/mman.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <unistd.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define TEST_PAGES 2 > +#define TEST_NODES 2 > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages06"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +int main(int argc, char **argv) > +{ > + unsigned int i; > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + unsigned int from_node = 0; > + unsigned int to_node; > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[TEST_PAGES] = { 0 }; > + int nodes[TEST_PAGES]; > + int status[TEST_PAGES]; > + int ret; > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_pages_on_node(pages, TEST_PAGES, from_node); > + if (ret == -1) > + continue; > + > + to_node = numa_max_node() + 1; > + for (i = 0; i < TEST_PAGES; i++) > + nodes[i] = to_node; > + > + ret = numa_move_pages(0, TEST_PAGES, pages, nodes, > + status, MPOL_MF_MOVE); > + TEST_ERRNO = errno; > + if (ret == -1 && errno == ENODEV) > + tst_resm(TPASS, "move_pages failed with " > + "ENODEV as expected"); > + else > + tst_resm(TFAIL, "move pages did not fail " > + "with ENODEV"); > + > + free_pages(pages, TEST_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + check_config(TEST_NODES); > + > + /* Pause if that option was specified > + * TEST_PAUSE contains the code to fork the test with the -c option. > + */ > + TEST_PAUSE; > +} > + > +/* > + * cleanup() - performs all ONE TIME cleanup for this test at completion > + */ > +void > +cleanup(void) > +{ > + /* > + * print timing stats if that option was specified. > + * print errno log if that option was specified. > + */ > + TEST_CLEANUP; > + > + /* exit with return code appropriate for results */ > + tst_exit(); > + /*NOTREACHED*/ > +} > Index: ltp-mod/testcases/kernel/syscalls/move_pages/move_pages07.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages07.c 2008-07-10 08:19:30.000000000 +0530 > @@ -0,0 +1,171 @@ > +/* > + * Copyright (c) 2008 Vijay Kumar B. <vij...@br...> > + * > + * Based on testcases/kernel/syscalls/waitpid/waitpid01.c > + * Original copyright message: > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * NAME > + * move_pages07.c > + * > + * DESCRIPTION > + * Failure when PID is invalid. > + * > + * ALGORITHM > + * > + * 1. Pass a non-existent pid to move_pages(). > + * 2. Check if errno is set to ESRCH. > + * > + * USAGE: <for command-line> > + * move_pages07 [-c n] [-i n] [-I x] [-P x] [-t] > + * where, -c n : Run n copies concurrently. > + * -i n : Execute test n times. > + * -I x : Execute test for x seconds. > + * -P x : Pause for x seconds between iterations. > + * -t : Turn on syscall timing. > + * > + * History > + * 05/2008 Vijay Kumar > + * Initial Version. > + * > + * Restrictions > + * None > + */ > + > +#include <sys/mman.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <unistd.h> > +#include <errno.h> > +#include <numa.h> > + > +#include <test.h> > +#include <usctest.h> > + > +#include "move_pages_support.h" > + > +#define TEST_PAGES 2 > +#define TEST_NODES 2 > + > +void setup(void); > +void cleanup(void); > + > +char *TCID = "move_pages07"; > +int TST_TOTAL = 1; > +extern int Tst_count; > + > +int main(int argc, char **argv) > +{ > + unsigned int i; > + int lc; /* loop counter */ > + char *msg; /* message returned from parse_opts */ > + unsigned int from_node = 0; > + unsigned int to_node = 1; > + > + /* parse standard options */ > + msg = parse_opts(argc, argv, (option_t *) NULL, NULL); > + if (msg != NULL) { > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + tst_exit(); > + /* NOTREACHED */ > + } > + > + setup(); > + > + /* check for looping state if -i option is given */ > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + void *pages[TEST_PAGES] = { 0 }; > + int nodes[TEST_PAGES]; > + int status[TEST_PAGES]; > + int ret; > + int ipid; > + > + /* reset Tst_count in case we are looping */ > + Tst_count = 0; > + > + ret = alloc_pages_on_node(pages, TEST_PAGES, from_node); > + if (ret == -1) > + continue; > + > + for (i = 0; i < TEST_PAGES; i++) > + nodes[i] = to_node; > + > + ipid = fork(); > + if (ipid == -1) { > + tst_resm(TBROK, "fork failed: %s", strerror(errno)); > + goto err_free_pages; > + } if (ipid == 0) > + exit(0); > + > + wait(NULL); > + > + ret = numa_move_pages(ipid, TEST_PAGES, pages, nodes, > + status, MPOL_MF_MOVE); > + TEST_ERRNO = errno; > + if (ret == -1 && errno == ESRCH) > + tst_resm(TPASS, "move_pages failed with " > + "ESRCH as expected"); > + else > + tst_resm(TFAIL, "move pages did not fail " > + "with ESRCH"); > + > + err_free_pages: > + free_pages(pages, TEST_PAGES); > + } > + > + cleanup(); > + /* NOT REACHED */ > + > + return 0; > +} > + > +/* > + * setup() - performs all ONE TIME setup for this test > + */ > +void > +setup(void) > +{ > + /* capture signals */ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + > + check_config(TEST_NODES); > + > + /* Pa... [truncated message content] |