Hi Christoph/Tony/Helge, Vijay has recently submitted the following testcases for move_pages() syscall. Can you kindly review the test code and provide your feedback. We would be integrating this code into LTP soon. Regards-- Subrata From: Vijay Kumar <vijaykumar@xxxxxxxxxxxx> Hi Subrata, I have updated the patch, I have also written the rest of ther testcases. It seems Suzuki is busy, I am yet to get review comments from Suzuki. The following fixes have been made to original patch. * Not using linux/mempolicy.h now, using numaif.h instead. This was causing a build break for older kernels. * Using a wrapper script to invoke the test case programs. The wrapper script checks if the test case program exists before invoking it. * Using semaphores to execute parent and child test processes in lock step. The following test cases are not implemented * Test case for errno = EACCES - not sure how to generate this error. Tried with set_mempolicy() but does not seem to work. * Test case for status[x] = -EFAULT - generating a invalid address that works for all configurations seems to be hard. * Test case for status[x] = -EBUSY - not sure how to generate this error. The following test case has been implemented but fails. I guess it's a bug in the implemenation or a bug in the man page. * Test case for status[x] = -EPERM - man page says this occurs for mlocked pages, but this does not seem to be the case. Signed-off-by: Vijay Kumar <vijaykumar@xxxxxxxxxxxx> 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-06-29 22:04:41.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_page12.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_page12.mode: + @/bin/sh ./move_pages12.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-06-29 09:56:02.000000000 +0530 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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(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-06-29 09:56:02.000000000 +0530 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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; + } + + verify_pages_on_node(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-06-29 09:56:02.000000000 +0530 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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(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-06-29 22:04:00.000000000 +0530 @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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 <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); +} + +/* + * verify_pages_on_nodes() - verify pages are in specified nodes + * @status: the NUMA node of each page + * @num: the no. of pages + * @nodes: the expected NUMA nodes + */ +void +verify_pages_on_nodes(int *status, unsigned int num, int *nodes) +{ + unsigned int i; + + for (i = 0; i < num; i++) { + if (status[i] != nodes[i]) { + tst_resm(TFAIL, "page %d on node %d, " + "expected on node %d", i, + status[i], nodes[i]); + return; + } + } + + tst_resm(TPASS, "pages are present in expected nodes"); +} + +/* + * verify_pages_linear() - verify pages are interleaved + * @status: the NUMA node of each page + * @num: the no. of pages + */ +void +verify_pages_linear(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(status, num, nodes); +} + +/* + * verify_pages_on_node() - verify pages are in specified node + * @status: the NUMA node of each page + * @num: the no. of pages + * @node: the expected NUMA node + */ +void +verify_pages_on_node(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(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-06-29 22:04:28.000000000 +0530 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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(int *status, unsigned int num, int *nodes); +void verify_pages_linear(int *status, unsigned int num); +void verify_pages_on_node(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-06-29 22:04:41.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 +move_pages12 move_pages.sh 12 + Index: ltp-mod/runtest/syscalls =================================================================== --- ltp-mod.orig/runtest/syscalls 2008-06-29 09:55:58.000000000 +0530 +++ ltp-mod/runtest/syscalls 2008-06-29 22:04:41.000000000 +0530 @@ -445,6 +445,19 @@ #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 +move_pages12 move_pages.sh 12 + 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, pradeepkumars@xxxxxxxxxx -# -# 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, pradeepkumars@xxxxxxxxxx +# +# 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. <vijaykumar@xxxxxxxxxxxx> + * + * 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. <vijaykumar@xxxxxxxxxxxx> + * + * 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-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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 moving mlocked pages. + * + * ALGORITHM + * + * 1. Pass a pointer to a mlocked page to to move_pages(). + * 2. Check if the corresponding status is set to -EPERM. + * + * 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 +#define MLOCKED_PAGE 0 + +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 = 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, TEST_PAGES, from_node); + if (ret == -1) + continue; + + ret = mlock(&pages[MLOCKED_PAGE], onepage); + if (ret == -1) { + tst_resm(TBROK, "mlocking page failed: %s", + strerror(errno)); + 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[MLOCKED_PAGE] == -EPERM) + tst_resm(TPASS, "status[%d] set to expected -EPERM", + MLOCKED_PAGE); + else + tst_resm(TFAIL, "status[%d] is %d", MLOCKED_PAGE, + status[MLOCKED_PAGE]); + + err_free_pages: + /* This is capable of freeing both mlocked and + * non-mlocked 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_pages07.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages07.c 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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 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_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; + + /* 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_pages08.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages08.c 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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_pages08.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_pages08 [-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_pages08"; +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); + + /* 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_pages09.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages09.c 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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_pages09.c + * + * DESCRIPTION + * Failure when the no. of pages is ULONG_MAX. + * + * ALGORITHM + * + * 1. Pass ULONG_MAX pages to move_pages(). + * 2. Check if errno is set to E2BIG. + * + * USAGE: <for command-line> + * move_pages09 [-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_pages09"; +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, ULONG_MAX, pages, nodes, + status, MPOL_MF_MOVE); + TEST_ERRNO = errno; + if (ret == -1 && errno == E2BIG) + tst_resm(TPASS, "move_pages failed with " + "E2BIG as expected"); + else + tst_resm(TFAIL, "move pages did not fail " + "with E2BIG"); + + 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_pages10.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages10.c 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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_pages10.c + * + * DESCRIPTION + * Failure when all pages are in required node. + * + * ALGORITHM + * + * 1. Pass the actual NUMA node number for each page to move_pages(). + * 2. Check if errno is set to ENOENT. + * + * USAGE: <for command-line> + * move_pages10 [-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_pages10"; +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; + + /* 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] = from_node; + + ret = numa_move_pages(0, TEST_PAGES, pages, nodes, + status, MPOL_MF_MOVE); + TEST_ERRNO = errno; + if (ret == -1 && errno == ENOENT) + tst_resm(TPASS, "move_pages failed with " + "ENOENT as expected"); + else + tst_resm(TFAIL, "move pages did not fail " + "with ENOENT"); + + 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_pages11.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages11.c 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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_pages11.c + * + * DESCRIPTION + * Failure when flags passed to move_pages is invalid. + * + * ALGORITHM + * + * 1. Pass invalid flag to move_pages(). + * 2. Check if errno is set to EINVAL. + * + * USAGE: <for command-line> + * move_pages11 [-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_pages11"; +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_STRICT); + TEST_ERRNO = errno; + if (ret == -1 && errno == EINVAL) + tst_resm(TPASS, "move_pages failed with " + "EINVAL as expected"); + else + tst_resm(TFAIL, "move_pages did not fail " + "with EINVAL"); + + 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_pages12.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages12.c 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@xxxxxxxxxxxx> + * + * 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_pages12.c + * + * DESCRIPTION + * Failure when trying move shared pages. + * + * ALGORITHM + * 1. Allocate a shared memory in NUMA node A. + * 2. Fork another process. + * 3. Use move_pages() to move the pages to NUMA node B, with the + * MPOL_MF_MOVE_ALL. + * 4. Check if errno is set to EPERM. + * + * USAGE: <for command-line> + * move_pages12 [-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 <pwd.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_pages12"; +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 == -1 && errno == EPERM) + tst_resm(TPASS, "move_pages failed with " + "EPERM as expected"); + else + tst_resm(TFAIL, "move_pages did not fail " + "with EPERM"); + + /* 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) +{ + struct passwd *ltpuser; + + /* capture signals */ + tst_sig(FORK, DEF_HANDLER, cleanup); + + check_config(TEST_NODES); + + if (geteuid() != 0) { + tst_resm(TBROK, "test must be run as root"); + tst_exit(); + } + + if ((ltpuser = getpwnam("nobody")) == NULL) { + tst_resm(TBROK, "'nobody' user not present"); + tst_exit(); + } + + if (seteuid(ltpuser->pw_uid) == -1) { + tst_resm(TBROK, "setting uid to %d failed", ltpuser->pw_uid); + tst_exit(); + } + + /* 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_pages12.mode.sh =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltp-mod/testcases/kernel/syscalls/move_pages/move_pages12.mode.sh 2008-06-29 22:04:41.000000000 +0530 @@ -0,0 +1,18 @@ +#!/bin/sh + +failed() { + echo "" + echo " ************** WARNING **************" + echo " Cannot change permission or ownership of \"move_pages12\"." + echo " Test move_pages12 will fail" + echo " Run "make install" as root." + echo " *************************************" + sleep 2 +} + +if [ -f move_pages12 ]; then + chown root move_pages12 || failed + chmod 04755 move_pages12 || failed +fi + +exit 0 -- To unsubscribe from this list: send the line "unsubscribe linux-numa" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html