From: Martin R. <mr...@us...> - 2004-08-24 20:31:03
|
Update of /cvsroot/ltp/ltp/testcases/kernel/syscalls/mincore In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11425 Added Files: Makefile mincore01.c mincore02.c Log Message: Moved mincore from paging to mincore directory --- NEW FILE: mincore01.c --- /* * * 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 * mincore01.c * * DESCRIPTION * Testcase to check the error conditions for mincore * * ALGORITHM * test1: * Invoke mincore() when the start address is not multiple of page size. * EINVAL * test2: * Invoke mincore()when the length has a non-positive value. EINVAL * test3: * Invoke mincore() when the vector points to an invalid address. EFAULT * test4: * Invoke mincore() when the starting address + length contained unmapped * memory. ENOMEM * test5: * Invoke mincore() when the length contained memory is not part of file. * ENOMEM * * USAGE: <for command-line> * mincore01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] * where, -c n : Run n copies concurrently. * -e : Turn on errno logging. * -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 * Author: Rajeev Tiwari: raj...@in... * 08/2004 Rajeev Tiwari : does a basic sanity check for the various error * conditions possible with the mincore system call. * * RESTRICTIONS * None */ #include <fcntl.h> #include <errno.h> #include <sys/mman.h> #include <stdlib.h> #include <limits.h> /* for PAGESIZE */ #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include "test.h" #include "usctest.h" #ifndef PAGESIZE #define PAGESIZE 4096 #endif void cleanup(void); void setup(void); void setup1(void); void setup2(void); void setup3(void); void setup4(void); void setup5(void); char *TCID= "mincore01"; int TST_TOTAL = 5; extern int Tst_count; char* file_pointer=NULL; char* global_pointer=NULL; char* global_vec=NULL; int len = 0; char *vec = NULL; int file_desc =0; struct stat *fst=NULL; char * file_name = NULL; int exp_enos[]={EINVAL,EINVAL,EFAULT, ENOMEM,ENOMEM}; struct test_case_t { char **addr; int len; int error; char **vector; void (*setupfunc)(); } TC[] = { { &file_pointer,0,0,&vec,setup1 }, { &file_pointer,0,0,&vec,setup2 }, { &file_pointer,0,0,&vec,setup3 }, { &file_pointer,0,0,&vec,setup4 }, { &file_pointer,0,0,&vec,setup5 } }; /* Uncomment the macro below to debug */ /* #define DEBUG_MODE 1 */ int main(int ac, char **av) { int lc; /* loop counter */ int i; char *msg; /* message returned from parse_opts */ /* parse standard options */ if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){ tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg); } setup(); /* global setup */ /* set up the expected errnos */ TEST_EXP_ENOS(exp_enos); /* The following loop checks looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { /* reset Tst_count in case we are looping */ Tst_count = 0; /* loop through the test cases */ for (i = 0; i < TST_TOTAL; i++) { /* perform test specific setup */ if (TC[i].setupfunc != NULL) { TC[i].setupfunc(); } #ifdef DEBUG_MODE printf("Before Calling mincore -->> Address : %x, len : %x, vector : %x\n", *(TC[i].addr), TC[i].len, *(TC[i].vector)); #endif TEST(mincore(*(TC[i].addr), TC[i].len, *(TC[i].vector))); if (TEST_RETURN != -1) { tst_resm(TFAIL, "call succeeded unexpectedly"); continue; } TEST_ERROR_LOG(TEST_ERRNO); if (TEST_ERRNO == TC[i].error) { tst_resm(TPASS, "expected failure - " "errno = %d : %s", TEST_ERRNO, strerror(TEST_ERRNO)); } else { tst_resm(TFAIL, "unexpected error - %d : %s - " "expected %d", TEST_ERRNO, strerror(TEST_ERRNO), TC[i].error); } } } cleanup(); return(0); /*NOTREACHED*/ } /* * setup1() - sets up conditions for the first test. the start address is not * multiple of page size */ void setup1() { /* resetting the value of file pointer and bitmap vector */ file_pointer = global_pointer; vec = global_vec; int size = 4096*2; *(TC[0].addr) = file_pointer + 1; TC[0].len = size; *(TC[0].vector) = vec; TC[0].error = EINVAL; } /* * setup2() - sets up conditions for the second test. the length has a * non-positive value */ void setup2() { /* resetting the value of file pointer and bitmap vector */ file_pointer = global_pointer; vec = global_vec; int size = 4096*2; *(TC[1].addr) = file_pointer; TC[1].len = -size; *(TC[1].vector) = vec; TC[1].error = EINVAL; } /* * setup3() - sets up conditions for the third test. the vector points to an * invalid address. */ void setup3() { /* resetting the value of file pointer and bitmap vector */ file_pointer = global_pointer; vec = global_vec; int size = 4096*2; *(TC[2].addr) = file_pointer; TC[2].len = size; *(TC[2].vector) = 0xC0000000; TC[2].error = EFAULT; } /* * setup4() - performs the setup for test4(the starting address + length * contained unmapped memory). we give the length of mapped file equal to 5 * times the mapped file size. */ void setup4() { /* resetting the value of file pointer and bitmap vector */ file_pointer = global_pointer; vec = global_vec; int size = 4096*10; *(TC[3].addr) = file_pointer; TC[3].len = size; *(TC[3].vector) = vec; TC[3].error = ENOMEM; } /* * setup5() - performs the setup related to the test5 * length contained memory is not part of file. The file size is 2 pages, * we give a offset of 2 pages as the starting address. */ void setup5() { int size = 4096; /* resetting the value of file pointer and bitmap vector */ file_pointer = global_pointer; vec = global_vec; *(TC[4].addr) = file_pointer+2*size; TC[4].len = size; *(TC[4].vector) = vec; TC[4].error = ENOMEM; } /* * setup() - performs all ONE TIME setup for this test */ void setup() { /* create a temporary buffer to fill two pages of data */ char *buf = malloc(4096*2); int counter; int size = 4096*2; int status; char *msg; for (counter =0; counter < size ; counter++) { *(buf+counter) = 'x'; } /* capture signals */ tst_sig(FORK, DEF_HANDLER, cleanup); /* Pause if that option was specified */ TEST_PAUSE; file_name = tmpnam(NULL); /* create a temporary file to be used */ if((file_desc = open(file_name,O_RDWR|O_CREAT))==-1) { tst_brkm(TBROK, cleanup, "Error in opening file - %s", msg); } /* fill the temporary file with two pages of data */ if((status=write(file_desc,buf,size))==-1) { tst_brkm(TBROK, cleanup, "Error in writing to the file - %s", msg); } /* collect the stats on the file to get the size */ fst = (struct stat *) malloc(sizeof(struct stat)); if((status=fstat(file_desc,fst))==-1) { tst_brkm(TBROK, cleanup, "Error in getting file stats - %s", msg); } /* map the file in memory */ if((file_pointer = (char *)mmap(NULL,(*fst).st_size,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,file_desc,NULL))==-1) { tst_brkm(TBROK, cleanup, "File cannot be mapped in memory - %s", msg); } /* Align to a multiple of PAGESIZE, assumed to be power of two */ file_pointer = (char *)(((int)file_pointer + PAGESIZE-1) & ~(PAGESIZE-1)); /* set the global pointer */ global_pointer = file_pointer; #ifdef DEBUG_MODE printf("After alignment file_pointer : %x\n", file_pointer); #endif /* initialize the vector buffer to collect the page info */ vec = malloc(4096*2); /* set the global vector */ global_vec = vec; } /* * cleanup() - performs all the ONE TIME cleanup for this test at completion * or premature exit. */ void cleanup() { /* * print timing status if that option was specified. * print errno log if that option was specified */ TEST_CLEANUP; close(file_desc); remove(file_name); /* exit with return code appropriate for results */ tst_exit(); } --- NEW FILE: Makefile --- # # 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 of file : Makefile # ########################################################################### CFLAGS+= -I../../../../include -O -g -Wall LOADLIBES+= -L../../../../lib -lltp SRCS=$(wildcard *.c) TARGETS=$(patsubst %.c,%,$(SRCS)) all: $(TARGETS) install: @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done clean: rm -f $(TARGETS) --- NEW FILE: mincore02.c --- /* * * 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 * mincore02.c * * DESCRIPTION * Testcase to check the error conditions for mincore * * ALGORITHM * test1: * This test case provides a functional validation for mincore system call. * we memory map a file and lock it in memory, we spin off a child process, * which shares the memory mapped file with the parent process. When the * child process executes the mincore system call , then it should read the * the same number of pages which were mapped and locked by parent process. * * USAGE: <for command-line> * ./mincore02 * * HISTORY * Author: Rajeev Tiwari: raj...@in... * 08/2004 Rajeev Tiwari : Provides a functional validation of mincore system * call. * * RESTRICTIONS * None */ /* Standard Include Files */ #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <errno.h> /* Harness Specific Include Files. */ #include "test.h" #include "usctest.h" /* comment out if you need to debug */ /* #define DEBUG_MODE 1 */ /* Extern Global Variables */ extern int Tst_count; /* counter for tst_xxx routines. */ extern char *TESTDIR; /* temporary dir created by tst_tmpdir() */ /* Global Variables */ char *TCID = "mincore02"; /* test program identifier. */ int TST_TOTAL = 1; /* total number of tests in this file. */ int LOOP = 0; /* this is needed to make the parent process run in tight loop */ int file_desc=0; /* this is for the file descriptor */ int status=0; /* this is for getting the final test case status */ struct stat fst; /* this is for capturing the file status eg size etc.. */ char *position=NULL; int pid=0; int p_size = 4096; int num_pages=0; int counter=0; int lock_pages=0; char * vec=NULL; /* Extern Global Functions */ /******************************************************************************/ /* */ /* Function: cleanup */ /* */ /* Description: Performs all one time clean up for this test on successful */ /* completion, premature exit or failure. Closes all temporary */ /* files, removes all temporary directories exits the test with */ /* appropriate return code by calling tst_exit() function. */ /* */ /* Input: None. */ /* */ /* Output: None. */ /* */ /* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ /* On success - Exits calling tst_exit(). With '0' return code. */ /* */ /******************************************************************************/ void cleanup() { /* Close all open file descriptors. */ /* Exit with appropriate return code. */ TEST_CLEANUP; close(file_desc); remove("./mincore02.txt"); tst_exit(); } /* Local Functions */ /******************************************************************************/ /* */ /* Function: setup */ /* */ /* Description: Performs all one time setup for this test. This function is */ /* typically used to capture signals, create temporary dirs */ /* and temporary files that may be used in the course of this */ /* test. */ /* */ /* Input: None. */ /* */ /* Output: None. */ /* */ /* Return: On failure - Exits by calling cleanup(). */ /* */ /* */ /******************************************************************************/ void setup() { char *buf = malloc(4096*4); int counter; int size = 4096*4; int status; char *msg; for (counter =0; counter < size ; counter++) { *(buf+counter) = 'x'; } /* create a temporary file to be used */ if((file_desc = open("./mincore02.txt",O_RDWR|O_CREAT))==-1) { tst_brkm(TBROK, cleanup, "Unable to open file for read/write. Error:%d, %s\n" , errno, strerror(errno)); } /* fill the temporary file with two pages of data */ if((status=write(file_desc,buf,size))==-1) { tst_brkm(TBROK, cleanup, "Error in writing to the file - %s", msg); } /* get the size of the file using fstat */ if((status = fstat(file_desc,&fst))==-1) { tst_brkm(TBROK, cleanup, "Unable to get file status Error:%d, %s\n", errno, strerror(errno)); } /* mmap the file in virtual address space in read , write and execute mode , the mapping should be shared */ if((position = (char *)mmap(0,fst.st_size,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,file_desc,0))==-1) { tst_brkm(TBROK, cleanup, "Unable to map file for read/write. Error:%d, %s\n", errno, strerror(errno)); } vec = malloc(4096*2); return; } /* this is a function executed by the parent process to wait for a terminating * signal from the child process */ void handler(int SIG){ LOOP=1; } /* main function */ int main(int argc, /* number of command line parameters */ char **argv) /* pointer to the array of the command line parameters. */ { /* perform global test setup, call setup() function. */ setup(); /* Print test Assertion using tst_resm() function with argument TINFO. */ tst_resm(TINFO, "Testing mlock system lock if it works\n"); /* Test Case Body. */ /* this time the file has been mapped to the virtual address space */ /* we can now lock specific portions of the file */ /* int mlock(const void *addr, size_t len) */ if((status = mlock(position,fst.st_size))==-1) { tst_brkm(TBROK, cleanup, "Unable to lock the file - %d, %s\n", errno, strerror(errno)); } /* at this point create two process */ /* register a signal handler */ //signal(SIGINT, handler); pid = fork(); if(pid!=0) { printf("Parent process with PID = %d\n", getpid()); signal(SIGINT, handler); /* RUN IN A INFINITE LOOP to be killed on receiving the signal */ while(LOOP==0); cleanup(); } else { printf("Child process with PID = %d\n", getpid()); sleep(3); /* code executed by the child process */ /* call the global setup function */ setup(); /* run mincore to verify if the page resides in the memory or not */ /* int mincore(void *start, size_t length, unsigned char *vec); */ /* vec must be large enough to contain length/PAGE_SIZE bytes. */ p_size = 4096; if(fst.st_size != 0) { num_pages = fst.st_size/p_size; if(fst.st_size % p_size != 0) { num_pages++; } } #ifdef DEBUG_MODE printf("fst.st_size = %d\n", fst.st_size); printf("num_pages = %d\n", num_pages); #endif vec = (char *)malloc(num_pages); if((status = mincore((void *)position,fst.st_size,vec))==-1) { tst_brkm(TBROK, cleanup, "Unable to execute mincore system call \n"); } /* the above vec should be filled with the page status */ /* check the status of the last bit for all the bytes / pages */ lock_pages = 0; for(counter = 0; counter < num_pages; counter++) { status =((int )(*vec))&1; if(status==1) lock_pages++; vec++; } if(lock_pages == num_pages) tst_resm(TPASS, "\n\n pages locked in memory are %d \n\n no of pages calculated by mincore are %d:",num_pages,lock_pages); else tst_resm(TFAIL,"mincore didn't work, not all the pages locked by parent process are there\n\n"); #ifdef DEBUG_MODE printf("Sending signal to parent\n"); #endif kill(getppid(),SIGINT); } } |