Hi Garrett, this is the *final* version, please review. On 01/07/2011 02:40 AM, [email protected] wrote: > From: Caspar Zhang <[email protected]> > > We get segfaults during testing mtest01 on a 5TB memory machine, the > problem was traced to the array pid_list[] went to overflow and > corrupted memory. This fix makes pid_list dynamically sized with > correct memory size to avoid overflow. > > v2: not split into different bits when allocating pid_list. > v3: 1) fix optargs: -b and -p should not be used at the same time. > 2) pre_mem maybe not initialized before using if -p option not used. > fix it by moving it outside ``if(maxpercent)'' block. > v4: fix code format. > > Signed-off-by: Caspar Zhang <[email protected]> > --- > testcases/kernel/mem/mtest01/mtest01.c | 409 > +++++++++++++++++--------------- > 1 files changed, 215 insertions(+), 194 deletions(-) > > diff --git a/testcases/kernel/mem/mtest01/mtest01.c > b/testcases/kernel/mem/mtest01/mtest01.c > index aee0d51..94b429a 100644 > --- a/testcases/kernel/mem/mtest01/mtest01.c > +++ b/testcases/kernel/mem/mtest01/mtest01.c > @@ -44,223 +44,244 @@ > > #include "test.h" > > +#define FIVE_HUNDRED_KB (unsigned long long)(500*1024*1024) > +#define ONE_MEGABYTE (unsigned long long)(1024*1024*1024) > +#define THREE_MEGABYTES (unsigned long long)(3*ONE_MEGABYTE) > + > char *TCID = "mtest01"; > int TST_TOTAL = 1; > - > int pid_count = 0; > > void handler(int signo) > { > - pid_count++; > + pid_count++; > } > > -int main(int argc, char* argv[]) { > - char* mem; > - float percent; > - unsigned int maxpercent=0, dowrite=0, verbose=0, j, c; > - unsigned long bytecount, alloc_bytes; > - unsigned long long original_maxbytes,maxbytes=0; > - unsigned long long pre_mem, post_mem; > - extern char* optarg; > - int chunksize = 1024*1024; /* one meg at a time by default */ > - struct sysinfo sstats; > - int i,pid_cntr; > - pid_t pid,pid_list[1000]; > - struct sigaction act; > - > - act.sa_handler = handler; > - act.sa_flags = 0; > - sigemptyset(&act.sa_mask); > - sigaction(SIGRTMIN, &act, 0); > - > - for (i=0;i<1000;i++) > - pid_list[i]=(pid_t)0; > - > - while ((c=getopt(argc, argv, "c:b:p:wvh")) != EOF) { > - switch((char)c) { > - case 'c': > - chunksize = atoi(optarg); > - break; > - case 'b': > - maxbytes = atoll(optarg); > - break; > - case 'p': > - maxpercent = atoi(optarg); > - if (maxpercent <= 0) { > - tst_resm(TFAIL, "ERROR: -p option requires number greater than 0"); > - exit(1);} > - if (maxpercent > 99) { > - tst_resm(TFAIL, "ERROR: -p option cannot be greater than 99"); > - exit(1);} > - break; > - case 'w': > - dowrite = 1; > - break; > - case 'v': > - verbose = 1; > - break; > - case 'h': > - default: > - printf("Usage: %s [-c <bytes>] [-b <bytes>|-p <percent>] [-v]\n", > argv[0]); > - printf("\t-c <num>\tsize of chunk in bytes to malloc on each > pass\n"); > - printf("\t-b <bytes>\tmaximum number of bytes to allocate before > stopping\n"); > - printf("\t-p <bytes>\tpercent of total memory used at which the > program stops\n"); > - printf("\t-w\t\twrite to the memory after allocating\n"); > - printf("\t-v\t\tverbose\n"); > - printf("\t-h\t\tdisplay usage\n"); > - exit(-1); > - } > - } > - > - sysinfo(&sstats); > - if (maxpercent) { > +int main(int argc, char* argv[]) > +{ > + char* mem; > + float percent; > + unsigned int maxpercent = 0, dowrite = 0, verbose=0, j, c; > + unsigned long bytecount, alloc_bytes, max_pids; > + unsigned long long original_maxbytes, maxbytes = 0; > + unsigned long long pre_mem, post_mem; > unsigned long long total_ram, total_free, D, C; > - percent=(float)maxpercent/100.00; > - > - total_ram=sstats.totalram; > - total_ram=total_ram+sstats.totalswap; > - > - total_free=sstats.freeram; > - total_free=total_free+sstats.freeswap; > - > - /* Total memory used needed to reach maxpercent */ > - D = percent*(sstats.mem_unit*total_ram); > - tst_resm(TINFO, "Total memory used needed to reach maxpercent = %llu > kbytes", D/1024); > - > - /* Total memory already used */ > - C = sstats.mem_unit*(total_ram-total_free); > - tst_resm(TINFO, "Total memory already used on system = %llu kbytes", > C/1024); > + extern char* optarg; > + int chunksize = 1024*1024; /* one meg at a time by default */ > + struct sysinfo sstats; > + int i, pid_cntr; > + pid_t pid, *pid_list; > + struct sigaction act; > > + act.sa_handler = handler; > + act.sa_flags = 0; > + sigemptyset(&act.sa_mask); > + sigaction(SIGRTMIN, &act, 0); > + > + while ((c = getopt(argc, argv, "c:b:p:wvh")) != EOF) > + { > + switch((char)c) > + { > + case 'c': > + chunksize = atoi(optarg); > + break; > + case 'b': > + if (maxpercent != 0) { > + tst_resm(TFAIL, "ERROR: -b option cannot be used with -p > option at the same time"); > + exit(1); > + } > + maxbytes = atoll(optarg); > + break; > + case 'p': > + if (maxbytes != 0) { > + tst_resm(TFAIL, "ERROR: -p option cannot be used with -b > option at the same time"); > + exit(1); > + } > + maxpercent = atoi(optarg); > + if (maxpercent <= 0) { > + tst_resm(TFAIL, "ERROR: -p option requires number > greater than 0"); > + exit(1); > + } > + if (maxpercent > 99) { > + tst_resm(TFAIL, "ERROR: -p option cannot be greater than > 99"); > + exit(1); > + } > + break; > + case 'w': > + dowrite = 1; > + break; > + case 'v': > + verbose = 1; > + break; > + case 'h': > + default: > + printf("Usage: %s [-c <bytes>] [-b <bytes>|-p <percent>] > [-v]\n", argv[0]); > + printf("\t-c <num>\tsize of chunk in bytes to malloc on each > pass\n"); > + printf("\t-b <bytes>\tmaximum number of bytes to allocate > before stopping\n"); > + printf("\t-p <bytes>\tpercent of total memory used at which > the program stops\n"); > + printf("\t-w\t\twrite to the memory after allocating\n"); > + printf("\t-v\t\tverbose\n"); > + printf("\t-h\t\tdisplay usage\n"); > + exit(-1); > + } > + } > + > + sysinfo(&sstats); > + total_ram = sstats.totalram + sstats.totalswap; > + total_free = sstats.freeram + sstats.freeswap; > /* Total Free Pre-Test RAM */ > - pre_mem = sstats.mem_unit*total_free; > - > - /* Are we already using more than maxpercent? */ > - if (C>D) { > - tst_resm(TFAIL, "More memory than the maximum amount you specified is > already being used"); > - exit(1); > + pre_mem = sstats.mem_unit * total_free; > + max_pids = total_ram / (unsigned long)FIVE_HUNDRED_KB + 1; > + > + if ((pid_list = malloc(max_pids * sizeof(pid_t))) == NULL) > + { > + tst_resm(TBROK|TERRNO, "malloc failed."); > + exit(1); > } > - else > - pre_mem = sstats.mem_unit*total_free; > + memset(pid_list, 0, max_pids * sizeof(pid_t)); > + > + /* Currently used memory */ > + C = sstats.mem_unit * (total_ram - total_free); > + tst_resm(TINFO, "Total memory already used on system = %llu kbytes", > C/1024); > + > + if (maxpercent) > + { > + percent = (float)maxpercent / 100.00; > > - /* set maxbytes to the extra amount we want to allocate */ > - maxbytes = D-C; > - tst_resm(TINFO, "Filling up %d%% of ram which is %llu kbytes", > maxpercent, maxbytes/1024); > - } > - original_maxbytes=maxbytes; > - i=0; > - pid_cntr=0; > - pid=fork(); > - if (pid != 0) > - pid_cntr++; > - pid_list[i]=pid; > + /* Desired memory needed to reach maxpercent */ > + D = percent * (sstats.mem_unit * total_ram); > + tst_resm(TINFO, "Total memory used needed to reach maxpercent = %llu > kbytes", D/1024); > + > + /* Are we already using more than maxpercent? */ > + if (C > D) > + { > + tst_resm(TFAIL, "More memory than the maximum amount you > specified is already being used"); > + free(pid_list); > + exit(1); > + } > + > + /* set maxbytes to the extra amount we want to allocate */ > + maxbytes = D - C; > + tst_resm(TINFO, "Filling up %d%% of ram which is %llu kbytes", > maxpercent, maxbytes/1024); > + } > + original_maxbytes = maxbytes; > + i = 0; > + pid_cntr = 0; > + pid = fork(); > + if (pid != 0) > + pid_cntr++; > + pid_list[i] = pid; > > #if defined (_s390_) /* s390's 31bit addressing requires smaller chunks */ > -#define FIVE_HUNDRED_KB (500*1024*1024) > -#define ONE_MEGABYTE (1024*1024*1024) > -#define THREE_MEGABYTES (3*ONE_MEGABYTE) > - while (pid != 0 && maxbytes > FIVE_HUNDRED_KB) > - { > - i++; > - maxbytes -= FIVE_HUNDRED_KB; > - pid = fork(); > - if (pid != 0) { > - pid_cntr++; > - pid_list[i] = pid; > + while (pid != 0 && maxbytes > FIVE_HUNDRED_KB) > + { > + i++; > + maxbytes -= FIVE_HUNDRED_KB; > + pid = fork(); > + if (pid != 0) > + { > + pid_cntr++; > + pid_list[i] = pid; > + } > } > - } > - if (maxbytes > FIVE_HUNDRED_KB) > - alloc_bytes FIVE_HUNDRED_KB; > - else > - alloc_bytes = (unsigned long) maxbytes; > - > + if (maxbytes > FIVE_HUNDRED_KB) > + alloc_bytes = FIVE_HUNDRED_KB; > + else > + alloc_bytes = (unsigned long) maxbytes; > + > #elif __WORDSIZE==32 > - while (pid != 0 && maxbytes > ONE_MEGABYTE) > - { > - i++; > - maxbytes -= ONE_MEGABYTE; > - pid = fork(); > - if (pid != 0) { > - pid_cntr++; > - pid_list[i]=pid; > + while (pid != 0 && maxbytes > ONE_MEGABYTE) > + { > + i++; > + maxbytes -= ONE_MEGABYTE; > + pid = fork(); > + if (pid != 0) > + { > + pid_cntr++; > + pid_list[i]=pid; > + } > } > - } > - if (maxbytes > ONE_MEGABYTE) > - alloc_bytes = ONE_MEGABYTE; > - else > - alloc_bytes = (unsigned long)maxbytes; > - > + if (maxbytes > ONE_MEGABYTE) > + alloc_bytes = ONE_MEGABYTE; > + else > + alloc_bytes = (unsigned long)maxbytes; > + > #elif __WORDSIZE==64 > - while (pid!=0 && maxbytes > THREE_MEGABYTES) > - { > - i++; > - maxbytes -= THREE_MEGABYTES; > - pid=fork(); > - if (pid != 0) { > - pid_cntr++; > - pid_list[i] = pid; > - } > - } > - if (maxbytes > THREE_MEGABYTES) > - alloc_bytes = THREE_MEGABYTES; > - else > - alloc_bytes = maxbytes; > -#endif > - > - if (pid == 0) /** CHILD **/ > - { > - bytecount=chunksize; > - while (1) { > - if ((mem = (char*)malloc(chunksize)) == NULL) { > - tst_resm(TINFO, "stopped at %lu bytes", bytecount); > - exit(1); > - } > - if (dowrite) > - for (j=0; j<chunksize; j++) > - *(mem+j)='a'; > - if (verbose) > - tst_resm(TINFO, "allocated %lu bytes chunksize is %d", bytecount, > chunksize); > - bytecount+=chunksize; > - if (alloc_bytes && (bytecount >= alloc_bytes)) > - break; > + while (pid!=0 && maxbytes > THREE_MEGABYTES) > + { > + i++; > + maxbytes -= THREE_MEGABYTES; > + pid = fork(); > + if (pid != 0) > + { > + pid_cntr++; > + pid_list[i] = pid; > + } > } > - if (dowrite) > - tst_resm(TINFO, "... %lu bytes allocated and used.", bytecount); > + if (maxbytes > THREE_MEGABYTES) > + alloc_bytes = THREE_MEGABYTES; > else > - tst_resm(TINFO, "... %lu bytes allocated only.", bytecount); > - kill(getppid(),SIGRTMIN); > - while (1) > - sleep(1); > - } > - else /** PARENT **/ > - { > - > - i=0; > - sysinfo(&sstats); > + alloc_bytes = maxbytes; > +#endif > > - if (dowrite) > + if (pid == 0) /** CHILD **/ > { > - /* Total Free Post-Test RAM */ > - post_mem = (unsigned long long)sstats.mem_unit*sstats.freeram; > - post_mem = post_mem+((unsigned long > long)sstats.mem_unit*sstats.freeswap); > - > - while ((((unsigned long long)pre_mem - post_mem) < (unsigned long > long)original_maxbytes) && > - (pid_count < pid_cntr) ) > - { > - sleep(1); > - sysinfo(&sstats); > - post_mem = (unsigned long long)sstats.mem_unit*sstats.freeram; > - post_mem = post_mem+((unsigned long > long)sstats.mem_unit*sstats.freeswap); > - } > + bytecount = chunksize; > + while (1) > + { > + if ((mem = malloc(chunksize)) == NULL) > + { > + tst_resm(TBROK|TERRNO, "stopped at %lu bytes", bytecount); > + free(pid_list); > + exit(1); > + } > + if (dowrite) > + for (j = 0; j < chunksize; j++) > + *(mem+j) = 'a'; > + if (verbose) > + tst_resm(TINFO, "allocated %lu bytes chunksize is %d", > bytecount, chunksize); > + bytecount += chunksize; > + if (alloc_bytes && bytecount >= alloc_bytes) > + break; > + } > + if (dowrite) > + tst_resm(TINFO, "... %lu bytes allocated and used.", bytecount); > + else > + tst_resm(TINFO, "... %lu bytes allocated only.", bytecount); > + kill(getppid(), SIGRTMIN); > + while (1) > + sleep(1); > } > - while (pid_list[i]!=0) > + else /** PARENT **/ > { > - kill(pid_list[i],SIGKILL); > - i++; > + i = 0; > + sysinfo(&sstats); > + > + if (dowrite) > + { > + /* Total Free Post-Test RAM */ > + post_mem = (unsigned long long)sstats.mem_unit * sstats.freeram; > + post_mem = post_mem + (unsigned long long)sstats.mem_unit * > sstats.freeswap; > + > + while ((((unsigned long long)pre_mem - post_mem) < (unsigned > long long)original_maxbytes) && > + (pid_count < pid_cntr)) > + { > + sleep(1); > + sysinfo(&sstats); > + post_mem = (unsigned long long)sstats.mem_unit * > sstats.freeram; > + post_mem = post_mem + (unsigned long long)sstats.mem_unit * > sstats.freeswap; > + } > + } > + while (pid_list[i] != 0) > + { > + kill(pid_list[i], SIGKILL); > + i++; > + } > + if (dowrite) > + tst_resm(TPASS, "%llu kbytes allocated and used.", > original_maxbytes/1024); > + else > + tst_resm(TPASS, "%llu kbytes allocated only.", > original_maxbytes/1024); > } > - if (dowrite) > - tst_resm(TPASS, "%llu kbytes allocated and used.", > original_maxbytes/1024); > - else > - tst_resm(TPASS, "%llu kbytes allocated only.", original_maxbytes/1024); > - } > - exit(0); > -} > \ No newline at end of file > + free(pid_list); > + exit(0); > +}
-- Quality Assurance Associate (Kernel) in Red Hat Software (Beijing) Co., R&D Branch TEL: +86-10-62608150 WEB: http://www.redhat.com/ -- C-A-S-P-A-R, Caspar /kæspɑ:/ ;-) ------------------------------------------------------------------------------ Learn how Oracle Real Application Clusters (RAC) One Node allows customers to consolidate database storage, standardize their database environment, and, should the need arise, upgrade to a full multi-node Oracle RAC database without downtime or disruption http://p.sf.net/sfu/oracle-sfdevnl _______________________________________________ Ltp-list mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ltp-list
