* [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework
@ 2022-10-12 14:48 Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework Edward Liaw via ltp
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Edward Liaw via ltp @ 2022-10-12 14:48 UTC (permalink / raw)
To: ltp; +Cc: kernel-team
v4->v5:
* reformat top level comment to docparse format
* reduce amount of verbose comments
* clean up file size bounds definitions
* make finished variable volatile for >1 retries
* remove unnecessary pidarray because offloaded to test harness
* remove unnecessary sig blocks
v3->v4:
* squash previous changes
* set defaults of nprocs=20 and max_runtime=12
* clean up comments
* return TBROK instead of TFAIL for unexpected failures
v2->v3:
* apply make check lint suggestions
* refactor cleanup
* use SAFE_FORK
* update license
v1->v2:
* clean up formatting
* remove accidental change to header comment
* use SAFE_MMAP
v0->v1:
* use tst_test framework
* use FILE_OFFSET_BITS=64 instead of LARGE_FILE
* use safe macros
Edward Liaw (5):
mmapstress01: refactor to tst_test framework
mmapstress01: format comments
mmapstress01: define fsize bounds by file offset bits
mmapstress01: remove unnecessary pidarray
mmapstress01: move sighandler to setup and remove sig blocks
testcases/kernel/mem/mmapstress/Makefile | 2 +
.../kernel/mem/mmapstress/mmapstress01.c | 865 +++++-------------
2 files changed, 245 insertions(+), 622 deletions(-)
--
2.38.0.rc1.362.ged0d419d3c-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework
2022-10-12 14:48 [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework Edward Liaw via ltp
@ 2022-10-12 14:48 ` Edward Liaw via ltp
2022-10-18 9:42 ` Richard Palethorpe
2022-10-12 14:48 ` [LTP] [PATCH v5 2/5] mmapstress01: format comments Edward Liaw via ltp
` (3 subsequent siblings)
4 siblings, 1 reply; 7+ messages in thread
From: Edward Liaw via ltp @ 2022-10-12 14:48 UTC (permalink / raw)
To: ltp; +Cc: kernel-team
Use ltp framework and apply make check corrections. Reorder functions
and variables. Use safe macros.
Drop leavefile option.
Build tests with FILE_OFFSET_BITS=64 instead of doing LARGE_FILE checks
to switch between 32 and 64 bit types and syscalls.
Set default nprocs to 20.
Signed-off-by: Edward Liaw <edliaw@google.com>
---
testcases/kernel/mem/mmapstress/Makefile | 2 +
.../kernel/mem/mmapstress/mmapstress01.c | 864 ++++++------------
2 files changed, 276 insertions(+), 590 deletions(-)
diff --git a/testcases/kernel/mem/mmapstress/Makefile b/testcases/kernel/mem/mmapstress/Makefile
index 744f099d8..b30bd34b8 100644
--- a/testcases/kernel/mem/mmapstress/Makefile
+++ b/testcases/kernel/mem/mmapstress/Makefile
@@ -5,3 +5,5 @@ top_srcdir ?= ../../../..
include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+mmapstress01: CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
index f425c223d..83d3f387d 100644
--- a/testcases/kernel/mem/mmapstress/mmapstress01.c
+++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
@@ -1,51 +1,10 @@
-/* IBM Corporation */
-/* 01/02/2003 Port to LTP avenkat@us.ibm.com */
-/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (c) International Business Machines Corp., 2003
- *
- *
- * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2003
+ * 01/02/2003 Port to LTP avenkat@us.ibm.com
+ * 06/30/2001 Port to Linux nsharoff@us.ibm.com
+ * 10/03/2022 Refactor to LTP framework edliaw@google.com
*/
-
-#define _GNU_SOURCE 1
-#include <stdio.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <limits.h>
-/***** LTP Port *****/
-#include "test.h"
-#define FAILED 0
-#define PASSED 1
-
-int local_flag = PASSED;
-char *TCID = "mmapstress01"; //tmnoextend
-FILE *temp;
-int TST_TOTAL = 1;
-
-int anyfail();
-void ok_exit();
-/***** ** ** *****/
-
/*
* This test stresses mmaps, without dealing with fragments or anything!
* It forks a specified number of children,
@@ -59,392 +18,100 @@ void ok_exit();
* or times out (if a timeout value is specified). When either of
* these things happens, it cleans up its kids, then checks the
* file to make sure it has the correct data.
- *
- * usage:
- * tmnoextend -p nprocs [-t minutes -f filesize -S sparseoffset
- * -r -o -m -l -d]
- * where:
- * -p nprocs - specifies the number of mapping children
- * to create. (nprocs + 1 children actually
- * get created, since one is the writer child)
- * -t minutes - specifies minutes to run. If not specified,
- * default is to run forever until a SIGINT
- * is received.
- * -f filesize - initial filesize (defaults to FILESIZE)
- * -S sparseoffset - when non-zero, causes a sparse area to
- * be left before the data, meaning that the
- * actual initial file size is sparseoffset +
- * filesize. Useful for testing large files.
- * (default is 0).
- * -r - randomize number of pages map children check.
- * (random % MAXLOOPS). If not specified, each
- * child checks MAXLOOPS pages.
- * -o - randomize offset of file to map. (default is 0)
- * -m - do random msync/fsyncs as well
- * -l - if set, the output file is not removed on
- * program exit.
- * -d - enable debug output
- *
- * Compile with -DLARGE_FILE to enable file sizes > 2 GB.
*/
+#define _GNU_SOURCE 1
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <float.h>
+#include "tst_test.h"
+
#define MAXLOOPS 500 /* max pages for map children to write */
-#define FILESIZE 4096 /* initial filesize set up by parent */
+#define TEST_FILE "mmapstress01.out"
#ifdef roundup
#undef roundup
#endif
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
-extern time_t time(time_t *);
-extern char *ctime(const time_t *);
-extern void *malloc(size_t);
-extern long lrand48(void);
-extern void srand(unsigned);
-extern void srand48(long);
-extern int rand(void);
-extern int atoi(const char *);
-
-char *usage =
- "-p nprocs [-t minutes -f filesize -S sparseoffset -r -o -m -l -d]";
-
-typedef unsigned char uchar_t;
-#define SIZE_MAX UINT_MAX
-
-unsigned int initrand(void);
-void finish(int sig);
-void child_mapper(char *file, unsigned procno, unsigned nprocs);
-int fileokay(char *file, uchar_t * expbuf);
-int finished = 0;
-int leavefile = 0;
-
-int debug = 0;
-#ifdef LARGE_FILE
-off64_t filesize = FILESIZE;
-off64_t sparseoffset = 0;
-#else /* LARGE_FILE */
-off_t filesize = FILESIZE;
-off_t sparseoffset = 0;
-#endif /* LARGE_FILE */
-unsigned randloops = 0;
-unsigned dosync = 0;
-unsigned do_offset = 0;
-unsigned pattern = 0;
-
-int main(int argc, char *argv[])
+static unsigned int initrand(void);
+
+static char *debug;
+static char *do_sync;
+static char *do_offset;
+static char *opt_filesize;
+static char *opt_nprocs;
+static char *opt_sparseoffset;
+static char *randloops;
+
+static int fd;
+static int finished;
+static int nprocs = 20;
+static long long filesize = 4096;
+static long long sparseoffset;
+static size_t pagesize;
+static unsigned int pattern;
+
+static struct tst_option options[] = {
+ {"d", &debug, "Enable debug output"},
+ {"f:", &opt_filesize, "Initial filesize (default 4096)"},
+ {"m", &do_sync, "Do random msync/fsyncs as well"},
+ {"o", &do_offset, "Randomize the offset of file to map"},
+ {"p:", &opt_nprocs,
+ "Number of mapping children to create (default 20)"},
+ {"r", &randloops,
+ "Randomize number of pages map children check (random % 500), "
+ "otherwise each child checks 500 pages"},
+ {"S:", &opt_sparseoffset,
+ "When non-zero, causes the sparse area to be left before the data, "
+ "so that the actual initial filesize is sparseoffset + filesize "
+ "(default 0)"},
+ {},
+};
+
+static void setup(void)
{
- char *progname;
- int fd;
- int c;
- extern char *optarg;
- unsigned nprocs = 0;
- unsigned procno;
- pid_t *pidarray = NULL;
- pid_t pid;
- uchar_t *buf = NULL;
- unsigned int seed;
int pagesize = sysconf(_SC_PAGE_SIZE);
- float alarmtime = 0;
- struct sigaction sa;
- unsigned i;
- int write_cnt;
- uchar_t data;
- int no_prob = 0;
- int wait_stat;
- time_t t;
-#ifdef LARGE_FILE
- off64_t bytes_left;
-#else /* LARGE_FILE */
- off_t bytes_left;
-#endif /* LARGE_FILE */
- const char *filename = "mmapstress01.out";
-
- progname = *argv;
- tst_tmpdir();
- if (argc < 2) {
- tst_brkm(TBROK, NULL, "usage: %s %s", progname, usage);
- }
- while ((c = getopt(argc, argv, "S:omdlrf:p:t:")) != -1) {
- switch (c) {
- case 'd':
- debug = 1;
- break;
- case 't':
- alarmtime = atof(optarg) * 60;
- break;
- case 'p':
- nprocs = atoi(optarg);
- break;
- case 'l':
- leavefile = 1;
- break;
- case 'f':
-#ifdef LARGE_FILE
- filesize = atoll(optarg);
-#else /* LARGE_FILE */
- filesize = atoi(optarg);
-#endif /* LARGE_FILE */
- if (filesize < 0) {
- (void)fprintf(stderr, "error: negative "
- "filesize\n");
- anyfail();
- }
- break;
- case 'r':
- randloops = 1;
- break;
- case 'm':
- dosync = 1;
- break;
- case 'o':
- do_offset = 1;
- break;
- case 'S':
-#ifdef LARGE_FILE
- sparseoffset = atoll(optarg);
-#else /* LARGE_FILE */
- sparseoffset = atoi(optarg);
-#endif /* LARGE_FILE */
- if (sparseoffset % pagesize != 0) {
- fprintf(stderr,
- "sparseoffset must be pagesize multiple\n");
- anyfail();
- }
- break;
- default:
- (void)fprintf(stderr, "usage: %s %s\n", progname,
- usage);
- tst_exit();
- }
- }
-
- /* nprocs is >= 0 since it's unsigned */
- if (nprocs > 255) {
- (void)fprintf(stderr, "invalid nprocs %d - (range 0-255)\n",
- nprocs);
- anyfail();
- }
+#if _FILE_OFFSET_BITS == 64
+ if (tst_parse_filesize(opt_filesize, &filesize, 0, LONG_MAX))
+#else
+ if (tst_parse_filesize(opt_filesize, &filesize, 0, INT_MAX))
+#endif
+ tst_brk(TBROK, "invalid initial filesize '%s'", opt_filesize);
- (void)time(&t);
+#if _FILE_OFFSET_BITS == 64
+ if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, LONG_MIN, LONG_MAX))
+#else
+ if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, INT_MIN, INT_MAX))
+#endif
+ tst_brk(TBROK, "invalid sparse offset '%s'", opt_sparseoffset);
+ if (sparseoffset % pagesize != 0)
+ tst_brk(TBROK, "sparseoffset must be pagesize multiple");
- seed = initrand();
- pattern = seed & 0xff;
+ if (tst_parse_int(opt_nprocs, &nprocs, 0, 255))
+ tst_brk(TBROK, "invalid number of mapping children '%s'",
+ opt_nprocs);
if (debug) {
-#ifdef LARGE_FILE
- (void)printf("creating file <%s> with %Ld bytes, pattern %d\n",
- filename, filesize, pattern);
-#else /* LARGE_FILE */
- (void)printf("creating file <%s> with %ld bytes, pattern %d\n",
- filename, filesize, pattern);
-#endif /* LARGE_FILE */
- if (alarmtime)
- (void)printf("running for %f minutes\n",
- alarmtime / 60);
- else
- (void)printf("running with no time limit\n");
- }
-
- /*
- * Plan for death by signal. User may have specified
- * a time limit, in which set an alarm and catch SIGALRM.
- * Also catch and cleanup with SIGINT.
- */
- sa.sa_handler = finish;
- sa.sa_flags = 0;
- if (sigemptyset(&sa.sa_mask)) {
- perror("sigemptyset error");
- goto cleanup;
- }
-
- if (sigaction(SIGINT, &sa, 0) == -1) {
- perror("sigaction error SIGINT");
- goto cleanup;
- }
- if (sigaction(SIGQUIT, &sa, 0) == -1) {
- perror("sigaction error SIGQUIT");
- goto cleanup;
- }
- if (sigaction(SIGTERM, &sa, 0) == -1) {
- perror("sigaction error SIGTERM");
- goto cleanup;
- }
-
- if (alarmtime) {
- if (sigaction(SIGALRM, &sa, 0) == -1) {
- perror("sigaction error");
- goto cleanup;
- }
- (void)alarm(alarmtime);
- }
-#ifdef LARGE_FILE
- if ((fd = open64(filename, O_CREAT | O_TRUNC | O_RDWR, 0664)) == -1) {
-#else /* LARGE_FILE */
- if ((fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0664)) == -1) {
-#endif /* LARGE_FILE */
- perror("open error");
- anyfail();
- }
-
- if ((buf = malloc(pagesize)) == NULL
- || (pidarray = malloc(nprocs * sizeof(pid_t))) == NULL) {
- perror("malloc error");
- anyfail();
- }
-
- for (i = 0; i < nprocs; i++)
- *(pidarray + i) = 0;
-
- for (i = 0, data = 0; i < pagesize; i++) {
- *(buf + i) = (data + pattern) & 0xff;
- if (++data == nprocs)
- data = 0;
- }
-#ifdef LARGE_FILE
- if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
-#else /* LARGE_FILE */
- if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
-#endif /* LARGE_FILE */
- perror("lseek");
- anyfail();
- }
- for (bytes_left = filesize; bytes_left; bytes_left -= c) {
- write_cnt = MIN(pagesize, (int)bytes_left);
- if ((c = write(fd, buf, write_cnt)) != write_cnt) {
- if (c == -1) {
- perror("write error");
- } else {
- (void)fprintf(stderr, "write: wrote %d of %d "
- "bytes\n", c, write_cnt);
- }
- (void)close(fd);
- (void)unlink(filename);
- anyfail();
- }
+ tst_res(TINFO, "creating file <%s> with %lld bytes, pattern %d",
+ TEST_FILE, filesize, pattern);
}
+}
- (void)close(fd);
-
- /*
- * Fork off mmap children.
- */
- for (procno = 0; procno < nprocs; procno++) {
- switch (pid = fork()) {
-
- case -1:
- perror("fork error");
- goto cleanup;
-
- case 0:
- child_mapper(filename, procno, nprocs);
- exit(0);
-
- default:
- pidarray[procno] = pid;
- }
- }
-
- /*
- * Now wait for children and refork them as needed.
- */
-
- while (!finished) {
- pid = wait(&wait_stat);
- /*
- * Block signals while processing child exit.
- */
-
- if (sighold(SIGALRM) || sighold(SIGINT)) {
- perror("sighold error");
- goto cleanup;
- }
-
- if (pid != -1) {
- /*
- * Check exit status, then refork with the
- * appropriate procno.
- */
- if (!WIFEXITED(wait_stat)
- || WEXITSTATUS(wait_stat) != 0) {
- (void)fprintf(stderr, "child exit with err "
- "<x%x>\n", wait_stat);
- goto cleanup;
- }
- for (i = 0; i < nprocs; i++)
- if (pid == pidarray[i])
- break;
- if (i == nprocs) {
- (void)fprintf(stderr, "unknown child pid %d, "
- "<x%x>\n", pid, wait_stat);
- goto cleanup;
- }
-
- if ((pid = fork()) == -1) {
- perror("fork error");
- pidarray[i] = 0;
- goto cleanup;
- } else if (pid == 0) { /* child */
- child_mapper(filename, i, nprocs);
- exit(0);
- } else
- pidarray[i] = pid;
- } else {
- /*
- * wait returned an error. If EINTR, then
- * normal finish, else it's an unexpected
- * error...
- */
- if (errno != EINTR || !finished) {
- perror("unexpected wait error");
- goto cleanup;
- }
- }
- if (sigrelse(SIGALRM) || sigrelse(SIGINT)) {
- perror("sigrelse error");
- goto cleanup;
- }
- }
-
- /*
- * Finished! Check the file for sanity, then kill all
- * the children and done!.
- */
-
- if (sighold(SIGALRM)) {
- perror("sighold error");
- goto cleanup;
- }
- (void)alarm(0);
- no_prob = 1;
-
-cleanup:
- for (i = 0; i < nprocs; i++)
- (void)kill(pidarray[i], SIGKILL);
-
- while (wait(&wait_stat) != -1 || errno != ECHILD)
- continue;
-
- if (no_prob) { /* only check file if no errors */
- if (!fileokay(filename, buf)) {
- (void)fprintf(stderr, "file data incorrect!\n");
- (void)printf(" leaving file <%s>\n", filename);
- /***** LTP Port *****/
- local_flag = FAILED;
- anyfail();
- /***** ** *****/
- } else {
- (void)printf("file data okay\n");
- if (!leavefile)
- (void)unlink(filename);
- }
- } else
- (void)printf(" leaving file <%s>\n", filename);
-
- (void)time(&t);
- //(void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port
- ok_exit();
- tst_exit();
+static void cleanup(void)
+{
+ if (fd > 0)
+ SAFE_CLOSE(fd);
}
/*
@@ -454,91 +121,51 @@ cleanup:
* determined based on nprocs & procno). After a specific number of
* iterations, it exits.
*/
-void child_mapper(char *file, unsigned procno, unsigned nprocs)
+static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
{
-#ifdef LARGE_FILE
- struct stat64 statbuf;
- off64_t filesize;
- off64_t offset;
-#else /* LARGE_FILE */
struct stat statbuf;
off_t filesize;
off_t offset;
-#endif /* LARGE_FILE */
size_t validsize;
size_t mapsize;
char *maddr = NULL, *paddr;
- int fd;
- size_t pagesize = sysconf(_SC_PAGE_SIZE);
- unsigned randpage;
+ unsigned int randpage;
unsigned int seed;
- unsigned loopcnt;
- unsigned nloops;
- unsigned mappages;
- unsigned i;
+ unsigned int loopcnt;
+ unsigned int nloops;
+ unsigned int mappages;
+ unsigned int i;
seed = initrand(); /* initialize random seed */
-#ifdef LARGE_FILE
- if (stat64(file, &statbuf) == -1) {
-#else /* LARGE_FILE */
- if (stat(file, &statbuf) == -1) {
-#endif /* LARGE_FILE */
- perror("stat error");
- anyfail();
- }
+ SAFE_STAT(file, &statbuf);
filesize = statbuf.st_size;
-#ifdef LARGE_FILE
- if ((fd = open64(file, O_RDWR)) == -1) {
-#else /* LARGE_FILE */
- if ((fd = open(file, O_RDWR)) == -1) {
-#endif /* LARGE_FILE */
- perror("open error");
- anyfail();
- }
+ fd = SAFE_OPEN(file, O_RDWR);
- if (statbuf.st_size - sparseoffset > SIZE_MAX) {
- fprintf(stderr, "size_t overflow when setting up map\n");
- anyfail();
- }
+ if (statbuf.st_size - sparseoffset > UINT_MAX)
+ tst_brk(TBROK, "size_t overflow when setting up map");
mapsize = (size_t) (statbuf.st_size - sparseoffset);
mappages = roundup(mapsize, pagesize) / pagesize;
offset = sparseoffset;
if (do_offset) {
int pageoffset = lrand48() % mappages;
int byteoffset = pageoffset * pagesize;
+
offset += byteoffset;
mapsize -= byteoffset;
mappages -= pageoffset;
}
nloops = (randloops) ? (lrand48() % MAXLOOPS) : MAXLOOPS;
- if (debug) {
-#ifdef LARGE_FILE
- (void)printf("child %d (pid %ld): seed %d, fsize %Ld, "
- "mapsize %d, off %Ld, loop %d\n",
- procno, getpid(), seed, filesize, mapsize,
- offset / pagesize, nloops);
-#else /* LARGE_FILE */
- (void)printf("child %d (pid %d): seed %d, fsize %ld, "
- "mapsize %ld, off %ld, loop %d\n",
- procno, getpid(), seed, filesize, (long)mapsize,
- offset / pagesize, nloops);
-#endif /* LARGE_FILE */
- }
-#ifdef LARGE_FILE
- if ((maddr = mmap64(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED,
- fd, offset)) == (caddr_t) - 1) {
-#else /* LARGE_FILE */
- if ((maddr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED,
- fd, offset)) == (caddr_t) - 1) {
-#endif /* LARGE_FILE */
- perror("mmap error");
- anyfail();
- }
+ if (debug)
+ tst_res(TINFO, "child %d (pid %d): seed %d, fsize %lld, mapsize %ld, off %lld, loop %d",
+ procno, getpid(), seed, (long long)filesize,
+ (long)mapsize, (long long)offset / pagesize, nloops);
- (void)close(fd);
+ maddr = SAFE_MMAP(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ offset);
+ SAFE_CLOSE(fd);
/*
* Now loop read/writing random pages.
@@ -554,15 +181,11 @@ void child_mapper(char *file, unsigned procno, unsigned nprocs)
for (i = procno; i < validsize; i += nprocs) {
if (*((unsigned char *)(paddr + i))
- != ((procno + pattern) & 0xff)) {
- (void)fprintf(stderr, "child %d: invalid data "
- "<x%x>", procno,
- *((unsigned char *)(paddr + i)));
- (void)fprintf(stderr, " at pg %d off %d, exp "
- "<x%x>\n", randpage, i,
- (procno + pattern) & 0xff);
- anyfail();
- }
+ != ((procno + pattern) & 0xff))
+ tst_brk(TFAIL, "child %d: invalid data <x%x>\n"
+ " at pg %d off %d, exp <x%x>", procno,
+ *((unsigned char *)(paddr + i)),
+ randpage, i, (procno + pattern) & 0xff);
/*
* Now write it.
@@ -570,139 +193,74 @@ void child_mapper(char *file, unsigned procno, unsigned nprocs)
*(paddr + i) = (procno + pattern) & 0xff;
}
}
- if (dosync) {
+ if (do_sync) {
/*
* Exercise msync() as well!
*/
randpage = lrand48() % mappages;
paddr = maddr + (randpage * pagesize); /* page address */
if (msync(paddr, (mappages - randpage) * pagesize,
- MS_SYNC) == -1) {
- anyfail();
- }
- }
- if (munmap(maddr, mapsize) == -1) {
- perror("munmap failed");
- local_flag = FAILED;
- anyfail();
+ MS_SYNC) == -1)
+ tst_brk(TBROK | TERRNO, "msync failed");
}
+ SAFE_MUNMAP(maddr, mapsize);
exit(0);
}
/*
* Make sure file has all the correct data.
*/
-int fileokay(char *file, uchar_t * expbuf)
+static void fileokay(char *file, unsigned char *expbuf)
{
-#ifdef LARGE_FILE
- struct stat64 statbuf;
-#else /* LARGE_FILE */
- struct stat statbuf;
-#endif /* LARGE_FILE */
- size_t mapsize;
- unsigned mappages;
- unsigned pagesize = sysconf(_SC_PAGE_SIZE);
- uchar_t readbuf[pagesize];
- int fd;
int cnt;
- unsigned i, j;
-
-#ifdef LARGE_FILE
- if ((fd = open64(file, O_RDONLY)) == -1) {
-#else /* LARGE_FILE */
- if ((fd = open(file, O_RDONLY)) == -1) {
-#endif /* LARGE_FILE */
- perror("open error");
- /***** LTP Port *****/
- local_flag = FAILED;
- anyfail();
- /***** ** *****/
- return 0;
- }
-#ifdef LARGE_FILE
- if (fstat64(fd, &statbuf) == -1) {
-#else /* LARGE_FILE */
- if (fstat(fd, &statbuf) == -1) {
-#endif /* LARGE_FILE */
- perror("stat error");
- /***** LTP Port *****/
- local_flag = FAILED;
- anyfail();
- /***** ** *****/
- return 0;
- }
-#ifdef LARGE_FILE
- if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
-#else /* LARGE_FILE */
- if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
-#endif /* LARGE_FILE */
- perror("lseek");
- anyfail();
- }
+ size_t mapsize;
+ struct stat statbuf;
+ unsigned char readbuf[pagesize];
+ unsigned int i, j;
+ unsigned int mappages;
+ unsigned int pagesize = sysconf(_SC_PAGE_SIZE);
- if (statbuf.st_size - sparseoffset > SIZE_MAX) {
- fprintf(stderr, "size_t overflow when setting up map\n");
- anyfail();
- }
+ fd = SAFE_OPEN(file, O_RDONLY);
+
+ SAFE_FSTAT(fd, &statbuf);
+ SAFE_LSEEK(fd, sparseoffset, SEEK_SET);
+
+ if (statbuf.st_size - sparseoffset > UINT_MAX)
+ tst_brk(TBROK, "size_t overflow when setting up map");
mapsize = (size_t) (statbuf.st_size - sparseoffset);
mappages = roundup(mapsize, pagesize) / pagesize;
for (i = 0; i < mappages; i++) {
- cnt = read(fd, readbuf, pagesize);
- if (cnt == -1) {
- perror("read error");
- /***** LTP Port *****/
- local_flag = FAILED;
- anyfail();
- /***** ** *****/
- return 0;
- } else if (cnt != pagesize) {
+ cnt = SAFE_READ(0, fd, readbuf, pagesize);
+ if ((unsigned int)cnt != pagesize) {
/*
* Okay if at last page in file...
*/
- if ((i * pagesize) + cnt != mapsize) {
- (void)fprintf(stderr, "read %d of %ld bytes\n",
- (i * pagesize) + cnt,
- (long)mapsize);
- close(fd);
- return 0;
- }
+ if ((i * pagesize) + cnt != mapsize)
+ tst_brk(TFAIL, "missing data: read %d of %ld bytes",
+ (i * pagesize) + cnt, (long)mapsize);
}
/*
* Compare read bytes of data.
*/
- for (j = 0; j < cnt; j++) {
- if (expbuf[j] != readbuf[j]) {
- (void)fprintf(stderr,
- "read bad data: exp %c got %c)",
- expbuf[j], readbuf[j]);
-#ifdef LARGE_FILE
- (void)fprintf(stderr, ", pg %d off %d, "
- "(fsize %Ld)\n", i, j,
- statbuf.st_size);
-#else /* LARGE_FILE */
- (void)fprintf(stderr, ", pg %d off %d, "
- "(fsize %ld)\n", i, j,
- statbuf.st_size);
-#endif /* LARGE_FILE */
- close(fd);
- return 0;
- }
+ for (j = 0; j < (unsigned int)cnt; j++) {
+ if (expbuf[j] != readbuf[j])
+ tst_brk(TFAIL,
+ "read bad data: exp %c got %c, pg %d off %d, (fsize %lld)",
+ expbuf[j], readbuf[j], i, j,
+ (long long)statbuf.st_size);
}
}
- close(fd);
-
- return 1;
+ SAFE_CLOSE(fd);
}
- /*ARGSUSED*/ void finish(int sig)
+static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
{
finished++;
- return;
}
-unsigned int initrand(void)
+static unsigned int initrand(void)
{
unsigned int seed;
@@ -718,21 +276,147 @@ unsigned int initrand(void)
seed = rand();
srand((unsigned int)time(NULL));
seed = (seed ^ rand()) % 100000;
- srand48((long int)seed);
- return (seed);
+ srand48((long)seed);
+ return seed;
}
-/***** LTP Port *****/
-void ok_exit(void)
+static void run(void)
{
- tst_resm(TPASS, "Test passed");
- tst_rmdir();
- tst_exit();
-}
+ int c;
+ int i;
+ int procno;
+ int wait_stat;
+ off_t bytes_left;
+ pid_t pid;
+ pid_t *pidarray = NULL;
+ sigset_t set_mask;
+ size_t write_cnt;
+ struct sigaction sa;
+ unsigned char data;
+ unsigned char *buf;
+ unsigned int seed;
-int anyfail(void)
-{
- tst_brkm(TFAIL, tst_rmdir, "Test failed");
+ pagesize = sysconf(_SC_PAGE_SIZE);
+ seed = initrand();
+ pattern = seed & 0xff;
+
+ /*
+ * Plan for death by signal or alarm.
+ * Also catch and cleanup with SIGINT.
+ */
+ sa.sa_handler = sighandler;
+ sa.sa_flags = 0;
+ SAFE_SIGEMPTYSET(&sa.sa_mask);
+ SAFE_SIGACTION(SIGINT, &sa, 0);
+ SAFE_SIGACTION(SIGQUIT, &sa, 0);
+ SAFE_SIGACTION(SIGTERM, &sa, 0);
+
+ SAFE_SIGACTION(SIGALRM, &sa, 0);
+ alarm(tst_remaining_runtime());
+
+ fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, 0664);
+
+ buf = SAFE_MALLOC(pagesize);
+ pidarray = SAFE_MALLOC(nprocs * sizeof(pid_t));
+
+ for (i = 0; i < nprocs; i++)
+ *(pidarray + i) = 0;
+
+ for (i = 0, data = 0; i < (int)pagesize; i++) {
+ *(buf + i) = (data + pattern) & 0xff;
+ if (++data == nprocs)
+ data = 0;
+ }
+ SAFE_LSEEK(fd, (off_t)sparseoffset, SEEK_SET);
+ for (bytes_left = filesize; bytes_left; bytes_left -= c) {
+ write_cnt = MIN((long long)pagesize, (long long)bytes_left);
+ c = SAFE_WRITE(1, fd, buf, write_cnt);
+ }
+ SAFE_CLOSE(fd);
+
+ /*
+ * Fork off mmap children.
+ */
+ for (procno = 0; procno < nprocs; procno++) {
+ switch (pid = SAFE_FORK()) {
+ case 0:
+ child_mapper(TEST_FILE, (unsigned int)procno, (unsigned int)nprocs);
+ exit(0);
+
+ default:
+ pidarray[procno] = pid;
+ }
+ }
+
+ /*
+ * Now wait for children and refork them as needed.
+ */
+
+ SAFE_SIGEMPTYSET(&set_mask);
+ SAFE_SIGADDSET(&set_mask, SIGALRM);
+ SAFE_SIGADDSET(&set_mask, SIGINT);
+ while (!finished) {
+ pid = wait(&wait_stat);
+ /*
+ * Block signals while processing child exit.
+ */
+
+ SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
+
+ if (pid != -1) {
+ /*
+ * Check exit status, then refork with the
+ * appropriate procno.
+ */
+ if (!WIFEXITED(wait_stat)
+ || WEXITSTATUS(wait_stat) != 0)
+ tst_brk(TBROK, "child exit with err <x%x>",
+ wait_stat);
+ for (i = 0; i < nprocs; i++)
+ if (pid == pidarray[i])
+ break;
+ if (i == nprocs)
+ tst_brk(TBROK, "unknown child pid %d, <x%x>",
+ pid, wait_stat);
+
+ pid = SAFE_FORK();
+ if (pid == 0) { /* child */
+ child_mapper(TEST_FILE, (unsigned int)i, (unsigned int)nprocs);
+ exit(0);
+ } else {
+ pidarray[i] = pid;
+ }
+ } else {
+ /*
+ * wait returned an error. If EINTR, then
+ * normal finish, else it's an unexpected
+ * error...
+ */
+ if (errno != EINTR || !finished)
+ tst_brk(TBROK | TERRNO,
+ "unexpected wait error");
+ }
+ SAFE_SIGPROCMASK(SIG_UNBLOCK, &set_mask, NULL);
+ }
+
+ SAFE_SIGEMPTYSET(&set_mask);
+ SAFE_SIGADDSET(&set_mask, SIGALRM);
+ SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
+ alarm(0);
+
+ /*
+ * Finished! Check the file for sanity.
+ */
+ fileokay(TEST_FILE, buf);
+ tst_res(TPASS, "file has expected data");
}
-/***** ** ** *****/
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .options = options,
+ .cleanup = cleanup,
+ .max_runtime = 12,
+ .needs_tmpdir = 1,
+ .forks_child = 1,
+};
--
2.38.0.rc1.362.ged0d419d3c-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v5 2/5] mmapstress01: format comments
2022-10-12 14:48 [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework Edward Liaw via ltp
@ 2022-10-12 14:48 ` Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 3/5] mmapstress01: define fsize bounds by file offset bits Edward Liaw via ltp
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Edward Liaw via ltp @ 2022-10-12 14:48 UTC (permalink / raw)
To: ltp; +Cc: kernel-team
Signed-off-by: Edward Liaw <edliaw@google.com>
---
.../kernel/mem/mmapstress/mmapstress01.c | 102 +++++++-----------
1 file changed, 41 insertions(+), 61 deletions(-)
diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
index 83d3f387d..dee73de5e 100644
--- a/testcases/kernel/mem/mmapstress/mmapstress01.c
+++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
@@ -5,19 +5,20 @@
* 06/30/2001 Port to Linux nsharoff@us.ibm.com
* 10/03/2022 Refactor to LTP framework edliaw@google.com
*/
-/*
- * This test stresses mmaps, without dealing with fragments or anything!
- * It forks a specified number of children,
- * all of whom mmap the same file, make a given number of accesses
- * to random pages in the map (reading & writing and comparing data).
- * Then the child exits and the parent forks another to take its place.
- * Each time a child is forked, it stats the file and maps the full
- * length of the file.
+/*\
+ * [Description]
+ * This test stresses mmaps, without dealing with fragments or anything!
+ * It forks a specified number of children,
+ * all of whom mmap the same file, make a given number of accesses
+ * to random pages in the map (reading & writing and comparing data).
+ * Then the child exits and the parent forks another to take its place.
+ * Each time a child is forked, it stats the file and maps the full
+ * length of the file.
*
- * This program continues to run until it either receives a SIGINT,
- * or times out (if a timeout value is specified). When either of
- * these things happens, it cleans up its kids, then checks the
- * file to make sure it has the correct data.
+ * This program continues to run until it either receives a SIGINT,
+ * or times out (if a timeout value is specified). When either of
+ * these things happens, it cleans up its kids, then checks the
+ * file to make sure it has the correct data.
*/
#define _GNU_SOURCE 1
@@ -102,10 +103,9 @@ static void setup(void)
tst_brk(TBROK, "invalid number of mapping children '%s'",
opt_nprocs);
- if (debug) {
+ if (debug)
tst_res(TINFO, "creating file <%s> with %lld bytes, pattern %d",
TEST_FILE, filesize, pattern);
- }
}
static void cleanup(void)
@@ -115,11 +115,11 @@ static void cleanup(void)
}
/*
- * Child process that reads/writes map. The child stats the file
- * to determine the size, maps the size of the file, then reads/writes
- * its own locations on random pages of the map (its locations being
- * determined based on nprocs & procno). After a specific number of
- * iterations, it exits.
+ * Child process that reads/writes map. The child stats the file
+ * to determine the size, maps the size of the file, then reads/writes
+ * its own locations on random pages of the map (its locations being
+ * determined based on nprocs & procno). After a specific number of
+ * iterations, it exits.
*/
static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
{
@@ -136,7 +136,7 @@ static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
unsigned int mappages;
unsigned int i;
- seed = initrand(); /* initialize random seed */
+ seed = initrand();
SAFE_STAT(file, &statbuf);
filesize = statbuf.st_size;
@@ -167,9 +167,7 @@ static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
offset);
SAFE_CLOSE(fd);
- /*
- * Now loop read/writing random pages.
- */
+ /* Loop read/writing random pages. */
for (loopcnt = 0; loopcnt < nloops; loopcnt++) {
randpage = lrand48() % mappages;
paddr = maddr + (randpage * pagesize); /* page address */
@@ -187,16 +185,12 @@ static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
*((unsigned char *)(paddr + i)),
randpage, i, (procno + pattern) & 0xff);
- /*
- * Now write it.
- */
+ /* Now write it. */
*(paddr + i) = (procno + pattern) & 0xff;
}
}
if (do_sync) {
- /*
- * Exercise msync() as well!
- */
+ /* Exercise msync() as well! */
randpage = lrand48() % mappages;
paddr = maddr + (randpage * pagesize); /* page address */
if (msync(paddr, (mappages - randpage) * pagesize,
@@ -207,9 +201,7 @@ static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
exit(0);
}
-/*
- * Make sure file has all the correct data.
- */
+/* Make sure file has all the correct data. */
static void fileokay(char *file, unsigned char *expbuf)
{
int cnt;
@@ -234,16 +226,12 @@ static void fileokay(char *file, unsigned char *expbuf)
for (i = 0; i < mappages; i++) {
cnt = SAFE_READ(0, fd, readbuf, pagesize);
if ((unsigned int)cnt != pagesize) {
- /*
- * Okay if at last page in file...
- */
+ /* Okay if at last page in file... */
if ((i * pagesize) + cnt != mapsize)
tst_brk(TFAIL, "missing data: read %d of %ld bytes",
(i * pagesize) + cnt, (long)mapsize);
}
- /*
- * Compare read bytes of data.
- */
+ /* Compare read bytes of data. */
for (j = 0; j < (unsigned int)cnt; j++) {
if (expbuf[j] != readbuf[j])
tst_brk(TFAIL,
@@ -265,12 +253,10 @@ static unsigned int initrand(void)
unsigned int seed;
/*
- * Initialize random seed... Got this from a test written
- * by scooter:
- * Use srand/rand to diffuse the information from the
- * time and pid. If you start several processes, then
- * the time and pid information don't provide much
- * variation.
+ * Use srand/rand to diffuse the information from the
+ * time and pid. If you start several processes, then
+ * the time and pid information don't provide much
+ * variation.
*/
srand((unsigned int)getpid());
seed = rand();
@@ -301,8 +287,8 @@ static void run(void)
pattern = seed & 0xff;
/*
- * Plan for death by signal or alarm.
- * Also catch and cleanup with SIGINT.
+ * Plan for death by signal or alarm.
+ * Also catch and cleanup with SIGINT.
*/
sa.sa_handler = sighandler;
sa.sa_flags = 0;
@@ -334,9 +320,7 @@ static void run(void)
}
SAFE_CLOSE(fd);
- /*
- * Fork off mmap children.
- */
+ /* Fork off mmap children. */
for (procno = 0; procno < nprocs; procno++) {
switch (pid = SAFE_FORK()) {
case 0:
@@ -348,9 +332,7 @@ static void run(void)
}
}
- /*
- * Now wait for children and refork them as needed.
- */
+ /* Now wait for children and refork them as needed. */
SAFE_SIGEMPTYSET(&set_mask);
SAFE_SIGADDSET(&set_mask, SIGALRM);
@@ -358,15 +340,15 @@ static void run(void)
while (!finished) {
pid = wait(&wait_stat);
/*
- * Block signals while processing child exit.
+ * Block signals while processing child exit.
*/
SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
if (pid != -1) {
/*
- * Check exit status, then refork with the
- * appropriate procno.
+ * Check exit status, then refork with the
+ * appropriate procno.
*/
if (!WIFEXITED(wait_stat)
|| WEXITSTATUS(wait_stat) != 0)
@@ -388,9 +370,9 @@ static void run(void)
}
} else {
/*
- * wait returned an error. If EINTR, then
- * normal finish, else it's an unexpected
- * error...
+ * wait returned an error. If EINTR, then
+ * normal finish, else it's an unexpected
+ * error...
*/
if (errno != EINTR || !finished)
tst_brk(TBROK | TERRNO,
@@ -404,9 +386,7 @@ static void run(void)
SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
alarm(0);
- /*
- * Finished! Check the file for sanity.
- */
+ /* Finished! Check the file for sanity. */
fileokay(TEST_FILE, buf);
tst_res(TPASS, "file has expected data");
}
--
2.38.0.rc1.362.ged0d419d3c-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v5 3/5] mmapstress01: define fsize bounds by file offset bits
2022-10-12 14:48 [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 2/5] mmapstress01: format comments Edward Liaw via ltp
@ 2022-10-12 14:48 ` Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 4/5] mmapstress01: remove unnecessary pidarray Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 5/5] mmapstress01: move sighandler to setup and remove sig blocks Edward Liaw via ltp
4 siblings, 0 replies; 7+ messages in thread
From: Edward Liaw via ltp @ 2022-10-12 14:48 UTC (permalink / raw)
To: ltp; +Cc: kernel-team
Signed-off-by: Edward Liaw <edliaw@google.com>
---
.../kernel/mem/mmapstress/mmapstress01.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
index dee73de5e..ea818ffcd 100644
--- a/testcases/kernel/mem/mmapstress/mmapstress01.c
+++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
@@ -36,6 +36,13 @@
#include <float.h>
#include "tst_test.h"
+#if _FILE_OFFSET_BITS == 64
+# define FSIZE_MIN LONG_MIN
+# define FSIZE_MAX LONG_MAX
+#else
+# define FSIZE_MIN INT_MIN
+# define FSIZE_MAX INT_MAX
+#endif
#define MAXLOOPS 500 /* max pages for map children to write */
#define TEST_FILE "mmapstress01.out"
@@ -83,18 +90,10 @@ static void setup(void)
{
int pagesize = sysconf(_SC_PAGE_SIZE);
-#if _FILE_OFFSET_BITS == 64
- if (tst_parse_filesize(opt_filesize, &filesize, 0, LONG_MAX))
-#else
- if (tst_parse_filesize(opt_filesize, &filesize, 0, INT_MAX))
-#endif
+ if (tst_parse_filesize(opt_filesize, &filesize, 0, FSIZE_MAX))
tst_brk(TBROK, "invalid initial filesize '%s'", opt_filesize);
-#if _FILE_OFFSET_BITS == 64
- if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, LONG_MIN, LONG_MAX))
-#else
- if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, INT_MIN, INT_MAX))
-#endif
+ if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, FSIZE_MIN, FSIZE_MAX))
tst_brk(TBROK, "invalid sparse offset '%s'", opt_sparseoffset);
if (sparseoffset % pagesize != 0)
tst_brk(TBROK, "sparseoffset must be pagesize multiple");
--
2.38.0.rc1.362.ged0d419d3c-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v5 4/5] mmapstress01: remove unnecessary pidarray
2022-10-12 14:48 [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework Edward Liaw via ltp
` (2 preceding siblings ...)
2022-10-12 14:48 ` [LTP] [PATCH v5 3/5] mmapstress01: define fsize bounds by file offset bits Edward Liaw via ltp
@ 2022-10-12 14:48 ` Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 5/5] mmapstress01: move sighandler to setup and remove sig blocks Edward Liaw via ltp
4 siblings, 0 replies; 7+ messages in thread
From: Edward Liaw via ltp @ 2022-10-12 14:48 UTC (permalink / raw)
To: ltp; +Cc: kernel-team
Signed-off-by: Edward Liaw <edliaw@google.com>
---
.../kernel/mem/mmapstress/mmapstress01.c | 25 ++++---------------
1 file changed, 5 insertions(+), 20 deletions(-)
diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
index ea818ffcd..de7da5b99 100644
--- a/testcases/kernel/mem/mmapstress/mmapstress01.c
+++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
@@ -62,7 +62,7 @@ static char *opt_sparseoffset;
static char *randloops;
static int fd;
-static int finished;
+static volatile int finished;
static int nprocs = 20;
static long long filesize = 4096;
static long long sparseoffset;
@@ -273,7 +273,6 @@ static void run(void)
int wait_stat;
off_t bytes_left;
pid_t pid;
- pid_t *pidarray = NULL;
sigset_t set_mask;
size_t write_cnt;
struct sigaction sa;
@@ -289,6 +288,7 @@ static void run(void)
* Plan for death by signal or alarm.
* Also catch and cleanup with SIGINT.
*/
+ finished = 0;
sa.sa_handler = sighandler;
sa.sa_flags = 0;
SAFE_SIGEMPTYSET(&sa.sa_mask);
@@ -302,10 +302,6 @@ static void run(void)
fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, 0664);
buf = SAFE_MALLOC(pagesize);
- pidarray = SAFE_MALLOC(nprocs * sizeof(pid_t));
-
- for (i = 0; i < nprocs; i++)
- *(pidarray + i) = 0;
for (i = 0, data = 0; i < (int)pagesize; i++) {
*(buf + i) = (data + pattern) & 0xff;
@@ -321,13 +317,11 @@ static void run(void)
/* Fork off mmap children. */
for (procno = 0; procno < nprocs; procno++) {
- switch (pid = SAFE_FORK()) {
- case 0:
+ pid = SAFE_FORK();
+
+ if (pid == 0) {
child_mapper(TEST_FILE, (unsigned int)procno, (unsigned int)nprocs);
exit(0);
-
- default:
- pidarray[procno] = pid;
}
}
@@ -353,19 +347,10 @@ static void run(void)
|| WEXITSTATUS(wait_stat) != 0)
tst_brk(TBROK, "child exit with err <x%x>",
wait_stat);
- for (i = 0; i < nprocs; i++)
- if (pid == pidarray[i])
- break;
- if (i == nprocs)
- tst_brk(TBROK, "unknown child pid %d, <x%x>",
- pid, wait_stat);
-
pid = SAFE_FORK();
if (pid == 0) { /* child */
child_mapper(TEST_FILE, (unsigned int)i, (unsigned int)nprocs);
exit(0);
- } else {
- pidarray[i] = pid;
}
} else {
/*
--
2.38.0.rc1.362.ged0d419d3c-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v5 5/5] mmapstress01: move sighandler to setup and remove sig blocks
2022-10-12 14:48 [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework Edward Liaw via ltp
` (3 preceding siblings ...)
2022-10-12 14:48 ` [LTP] [PATCH v5 4/5] mmapstress01: remove unnecessary pidarray Edward Liaw via ltp
@ 2022-10-12 14:48 ` Edward Liaw via ltp
4 siblings, 0 replies; 7+ messages in thread
From: Edward Liaw via ltp @ 2022-10-12 14:48 UTC (permalink / raw)
To: ltp; +Cc: kernel-team
Signed-off-by: Edward Liaw <edliaw@google.com>
---
.../kernel/mem/mmapstress/mmapstress01.c | 51 +++++--------------
1 file changed, 12 insertions(+), 39 deletions(-)
diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
index de7da5b99..cf8fb3b1f 100644
--- a/testcases/kernel/mem/mmapstress/mmapstress01.c
+++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
@@ -52,6 +52,7 @@
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
static unsigned int initrand(void);
+static void sighandler(int);
static char *debug;
static char *do_sync;
@@ -88,7 +89,17 @@ static struct tst_option options[] = {
static void setup(void)
{
- int pagesize = sysconf(_SC_PAGE_SIZE);
+ struct sigaction sa;
+
+ sa.sa_handler = sighandler;
+ sa.sa_flags = 0;
+ SAFE_SIGEMPTYSET(&sa.sa_mask);
+ SAFE_SIGACTION(SIGINT, &sa, 0);
+ SAFE_SIGACTION(SIGQUIT, &sa, 0);
+ SAFE_SIGACTION(SIGTERM, &sa, 0);
+ SAFE_SIGACTION(SIGALRM, &sa, 0);
+
+ pagesize = sysconf(_SC_PAGE_SIZE);
if (tst_parse_filesize(opt_filesize, &filesize, 0, FSIZE_MAX))
tst_brk(TBROK, "invalid initial filesize '%s'", opt_filesize);
@@ -273,9 +284,7 @@ static void run(void)
int wait_stat;
off_t bytes_left;
pid_t pid;
- sigset_t set_mask;
size_t write_cnt;
- struct sigaction sa;
unsigned char data;
unsigned char *buf;
unsigned int seed;
@@ -284,19 +293,7 @@ static void run(void)
seed = initrand();
pattern = seed & 0xff;
- /*
- * Plan for death by signal or alarm.
- * Also catch and cleanup with SIGINT.
- */
finished = 0;
- sa.sa_handler = sighandler;
- sa.sa_flags = 0;
- SAFE_SIGEMPTYSET(&sa.sa_mask);
- SAFE_SIGACTION(SIGINT, &sa, 0);
- SAFE_SIGACTION(SIGQUIT, &sa, 0);
- SAFE_SIGACTION(SIGTERM, &sa, 0);
-
- SAFE_SIGACTION(SIGALRM, &sa, 0);
alarm(tst_remaining_runtime());
fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, 0664);
@@ -326,23 +323,9 @@ static void run(void)
}
/* Now wait for children and refork them as needed. */
-
- SAFE_SIGEMPTYSET(&set_mask);
- SAFE_SIGADDSET(&set_mask, SIGALRM);
- SAFE_SIGADDSET(&set_mask, SIGINT);
while (!finished) {
pid = wait(&wait_stat);
- /*
- * Block signals while processing child exit.
- */
-
- SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
-
if (pid != -1) {
- /*
- * Check exit status, then refork with the
- * appropriate procno.
- */
if (!WIFEXITED(wait_stat)
|| WEXITSTATUS(wait_stat) != 0)
tst_brk(TBROK, "child exit with err <x%x>",
@@ -353,21 +336,11 @@ static void run(void)
exit(0);
}
} else {
- /*
- * wait returned an error. If EINTR, then
- * normal finish, else it's an unexpected
- * error...
- */
if (errno != EINTR || !finished)
tst_brk(TBROK | TERRNO,
"unexpected wait error");
}
- SAFE_SIGPROCMASK(SIG_UNBLOCK, &set_mask, NULL);
}
-
- SAFE_SIGEMPTYSET(&set_mask);
- SAFE_SIGADDSET(&set_mask, SIGALRM);
- SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
alarm(0);
/* Finished! Check the file for sanity. */
--
2.38.0.rc1.362.ged0d419d3c-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework
2022-10-12 14:48 ` [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework Edward Liaw via ltp
@ 2022-10-18 9:42 ` Richard Palethorpe
0 siblings, 0 replies; 7+ messages in thread
From: Richard Palethorpe @ 2022-10-18 9:42 UTC (permalink / raw)
To: Edward Liaw; +Cc: kernel-team, ltp
Hello,
In this particular case it would be easier for me if you squashed all
the commits.
I'll withhold my usual complaints about stress tests as this one already
existed. Some of the same issues I have with fanotify stress test
apply to this.
Your changes generally look good, but a few nits below.
Edward Liaw via ltp <ltp@lists.linux.it> writes:
> Use ltp framework and apply make check corrections. Reorder functions
> and variables. Use safe macros.
> Drop leavefile option.
> Build tests with FILE_OFFSET_BITS=64 instead of doing LARGE_FILE checks
> to switch between 32 and 64 bit types and syscalls.
> Set default nprocs to 20.
>
> Signed-off-by: Edward Liaw <edliaw@google.com>
> ---
> testcases/kernel/mem/mmapstress/Makefile | 2 +
> .../kernel/mem/mmapstress/mmapstress01.c | 864 ++++++------------
> 2 files changed, 276 insertions(+), 590 deletions(-)
>
> diff --git a/testcases/kernel/mem/mmapstress/Makefile b/testcases/kernel/mem/mmapstress/Makefile
> index 744f099d8..b30bd34b8 100644
> --- a/testcases/kernel/mem/mmapstress/Makefile
> +++ b/testcases/kernel/mem/mmapstress/Makefile
> @@ -5,3 +5,5 @@ top_srcdir ?= ../../../..
>
> include $(top_srcdir)/include/mk/testcases.mk
> include $(top_srcdir)/include/mk/generic_leaf_target.mk
> +
> +mmapstress01: CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
> diff --git a/testcases/kernel/mem/mmapstress/mmapstress01.c b/testcases/kernel/mem/mmapstress/mmapstress01.c
> index f425c223d..83d3f387d 100644
> --- a/testcases/kernel/mem/mmapstress/mmapstress01.c
> +++ b/testcases/kernel/mem/mmapstress/mmapstress01.c
> @@ -1,51 +1,10 @@
> -/* IBM Corporation */
> -/* 01/02/2003 Port to LTP avenkat@us.ibm.com */
> -/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
> +// SPDX-License-Identifier: GPL-2.0-or-later
> /*
> - * Copyright (c) International Business Machines Corp., 2003
> - *
> - *
> - * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * Copyright (c) International Business Machines Corp., 2003
> + * 01/02/2003 Port to LTP avenkat@us.ibm.com
> + * 06/30/2001 Port to Linux nsharoff@us.ibm.com
> + * 10/03/2022 Refactor to LTP framework edliaw@google.com
> */
> -
> -#define _GNU_SOURCE 1
> -#include <stdio.h>
> -#include <fcntl.h>
> -#include <signal.h>
> -#include <sys/mman.h>
> -#include <sys/wait.h>
> -#include <sys/stat.h>
> -#include <unistd.h>
> -#include <stdlib.h>
> -#include <errno.h>
> -#include <sys/types.h>
> -#include <limits.h>
> -/***** LTP Port *****/
> -#include "test.h"
> -#define FAILED 0
> -#define PASSED 1
> -
> -int local_flag = PASSED;
> -char *TCID = "mmapstress01"; //tmnoextend
> -FILE *temp;
> -int TST_TOTAL = 1;
> -
> -int anyfail();
> -void ok_exit();
> -/***** ** ** *****/
> -
> /*
> * This test stresses mmaps, without dealing with fragments or anything!
> * It forks a specified number of children,
> @@ -59,392 +18,100 @@ void ok_exit();
> * or times out (if a timeout value is specified). When either of
> * these things happens, it cleans up its kids, then checks the
> * file to make sure it has the correct data.
> - *
> - * usage:
> - * tmnoextend -p nprocs [-t minutes -f filesize -S sparseoffset
> - * -r -o -m -l -d]
> - * where:
> - * -p nprocs - specifies the number of mapping children
> - * to create. (nprocs + 1 children actually
> - * get created, since one is the writer child)
> - * -t minutes - specifies minutes to run. If not specified,
> - * default is to run forever until a SIGINT
> - * is received.
> - * -f filesize - initial filesize (defaults to FILESIZE)
> - * -S sparseoffset - when non-zero, causes a sparse area to
> - * be left before the data, meaning that the
> - * actual initial file size is sparseoffset +
> - * filesize. Useful for testing large files.
> - * (default is 0).
> - * -r - randomize number of pages map children check.
> - * (random % MAXLOOPS). If not specified, each
> - * child checks MAXLOOPS pages.
> - * -o - randomize offset of file to map. (default is 0)
> - * -m - do random msync/fsyncs as well
> - * -l - if set, the output file is not removed on
> - * program exit.
> - * -d - enable debug output
> - *
> - * Compile with -DLARGE_FILE to enable file sizes > 2 GB.
> */
>
> +#define _GNU_SOURCE 1
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <signal.h>
> +#include <sys/mman.h>
> +#include <sys/wait.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <limits.h>
> +#include <float.h>
> +#include "tst_test.h"
> +
> #define MAXLOOPS 500 /* max pages for map children to write */
> -#define FILESIZE 4096 /* initial filesize set up by parent */
> +#define TEST_FILE "mmapstress01.out"
>
> #ifdef roundup
> #undef roundup
> #endif
> #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
>
> -extern time_t time(time_t *);
> -extern char *ctime(const time_t *);
> -extern void *malloc(size_t);
> -extern long lrand48(void);
> -extern void srand(unsigned);
> -extern void srand48(long);
> -extern int rand(void);
> -extern int atoi(const char *);
> -
> -char *usage =
> - "-p nprocs [-t minutes -f filesize -S sparseoffset -r -o -m -l -d]";
> -
> -typedef unsigned char uchar_t;
> -#define SIZE_MAX UINT_MAX
> -
> -unsigned int initrand(void);
> -void finish(int sig);
> -void child_mapper(char *file, unsigned procno, unsigned nprocs);
> -int fileokay(char *file, uchar_t * expbuf);
> -int finished = 0;
> -int leavefile = 0;
> -
> -int debug = 0;
> -#ifdef LARGE_FILE
> -off64_t filesize = FILESIZE;
> -off64_t sparseoffset = 0;
> -#else /* LARGE_FILE */
> -off_t filesize = FILESIZE;
> -off_t sparseoffset = 0;
> -#endif /* LARGE_FILE */
> -unsigned randloops = 0;
> -unsigned dosync = 0;
> -unsigned do_offset = 0;
> -unsigned pattern = 0;
> -
> -int main(int argc, char *argv[])
> +static unsigned int initrand(void);
> +
> +static char *debug;
> +static char *do_sync;
> +static char *do_offset;
> +static char *opt_filesize;
> +static char *opt_nprocs;
> +static char *opt_sparseoffset;
> +static char *randloops;
> +
> +static int fd;
> +static int finished;
> +static int nprocs = 20;
The default should probably be scaled to the number of cpus (tst_ncpu)
with 20 being the max and reasonable minimum. Whether it should be 1:1
or some other ratio I don't know.
This could be handled in a later patch.
> +static long long filesize = 4096;
> +static long long sparseoffset;
> +static size_t pagesize;
> +static unsigned int pattern;
> +
> +static struct tst_option options[] = {
> + {"d", &debug, "Enable debug output"},
> + {"f:", &opt_filesize, "Initial filesize (default 4096)"},
> + {"m", &do_sync, "Do random msync/fsyncs as well"},
> + {"o", &do_offset, "Randomize the offset of file to map"},
> + {"p:", &opt_nprocs,
> + "Number of mapping children to create (default 20)"},
> + {"r", &randloops,
> + "Randomize number of pages map children check (random % 500), "
> + "otherwise each child checks 500 pages"},
> + {"S:", &opt_sparseoffset,
> + "When non-zero, causes the sparse area to be left before the data, "
> + "so that the actual initial filesize is sparseoffset + filesize "
> + "(default 0)"},
> + {},
> +};
> +
> +static void setup(void)
> {
> - char *progname;
> - int fd;
> - int c;
> - extern char *optarg;
> - unsigned nprocs = 0;
> - unsigned procno;
> - pid_t *pidarray = NULL;
> - pid_t pid;
> - uchar_t *buf = NULL;
> - unsigned int seed;
> int pagesize = sysconf(_SC_PAGE_SIZE);
> - float alarmtime = 0;
> - struct sigaction sa;
> - unsigned i;
> - int write_cnt;
> - uchar_t data;
> - int no_prob = 0;
> - int wait_stat;
> - time_t t;
> -#ifdef LARGE_FILE
> - off64_t bytes_left;
> -#else /* LARGE_FILE */
> - off_t bytes_left;
> -#endif /* LARGE_FILE */
> - const char *filename = "mmapstress01.out";
> -
> - progname = *argv;
> - tst_tmpdir();
> - if (argc < 2) {
> - tst_brkm(TBROK, NULL, "usage: %s %s", progname, usage);
> - }
>
> - while ((c = getopt(argc, argv, "S:omdlrf:p:t:")) != -1) {
> - switch (c) {
> - case 'd':
> - debug = 1;
> - break;
> - case 't':
> - alarmtime = atof(optarg) * 60;
> - break;
> - case 'p':
> - nprocs = atoi(optarg);
> - break;
> - case 'l':
> - leavefile = 1;
> - break;
> - case 'f':
> -#ifdef LARGE_FILE
> - filesize = atoll(optarg);
> -#else /* LARGE_FILE */
> - filesize = atoi(optarg);
> -#endif /* LARGE_FILE */
> - if (filesize < 0) {
> - (void)fprintf(stderr, "error: negative "
> - "filesize\n");
> - anyfail();
> - }
> - break;
> - case 'r':
> - randloops = 1;
> - break;
> - case 'm':
> - dosync = 1;
> - break;
> - case 'o':
> - do_offset = 1;
> - break;
> - case 'S':
> -#ifdef LARGE_FILE
> - sparseoffset = atoll(optarg);
> -#else /* LARGE_FILE */
> - sparseoffset = atoi(optarg);
> -#endif /* LARGE_FILE */
> - if (sparseoffset % pagesize != 0) {
> - fprintf(stderr,
> - "sparseoffset must be pagesize multiple\n");
> - anyfail();
> - }
> - break;
> - default:
> - (void)fprintf(stderr, "usage: %s %s\n", progname,
> - usage);
> - tst_exit();
> - }
> - }
> -
> - /* nprocs is >= 0 since it's unsigned */
> - if (nprocs > 255) {
> - (void)fprintf(stderr, "invalid nprocs %d - (range 0-255)\n",
> - nprocs);
> - anyfail();
> - }
> +#if _FILE_OFFSET_BITS == 64
> + if (tst_parse_filesize(opt_filesize, &filesize, 0, LONG_MAX))
> +#else
> + if (tst_parse_filesize(opt_filesize, &filesize, 0, INT_MAX))
> +#endif
> + tst_brk(TBROK, "invalid initial filesize '%s'", opt_filesize);
>
> - (void)time(&t);
> +#if _FILE_OFFSET_BITS == 64
> + if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, LONG_MIN, LONG_MAX))
> +#else
> + if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, INT_MIN, INT_MAX))
> +#endif
> + tst_brk(TBROK, "invalid sparse offset '%s'", opt_sparseoffset);
> + if (sparseoffset % pagesize != 0)
> + tst_brk(TBROK, "sparseoffset must be pagesize multiple");
>
> - seed = initrand();
> - pattern = seed & 0xff;
> + if (tst_parse_int(opt_nprocs, &nprocs, 0, 255))
> + tst_brk(TBROK, "invalid number of mapping children '%s'",
> + opt_nprocs);
>
> if (debug) {
> -#ifdef LARGE_FILE
> - (void)printf("creating file <%s> with %Ld bytes, pattern %d\n",
> - filename, filesize, pattern);
> -#else /* LARGE_FILE */
> - (void)printf("creating file <%s> with %ld bytes, pattern %d\n",
> - filename, filesize, pattern);
> -#endif /* LARGE_FILE */
> - if (alarmtime)
> - (void)printf("running for %f minutes\n",
> - alarmtime / 60);
> - else
> - (void)printf("running with no time limit\n");
> - }
> -
> - /*
> - * Plan for death by signal. User may have specified
> - * a time limit, in which set an alarm and catch SIGALRM.
> - * Also catch and cleanup with SIGINT.
> - */
> - sa.sa_handler = finish;
> - sa.sa_flags = 0;
> - if (sigemptyset(&sa.sa_mask)) {
> - perror("sigemptyset error");
> - goto cleanup;
> - }
> -
> - if (sigaction(SIGINT, &sa, 0) == -1) {
> - perror("sigaction error SIGINT");
> - goto cleanup;
> - }
> - if (sigaction(SIGQUIT, &sa, 0) == -1) {
> - perror("sigaction error SIGQUIT");
> - goto cleanup;
> - }
> - if (sigaction(SIGTERM, &sa, 0) == -1) {
> - perror("sigaction error SIGTERM");
> - goto cleanup;
> - }
> -
> - if (alarmtime) {
> - if (sigaction(SIGALRM, &sa, 0) == -1) {
> - perror("sigaction error");
> - goto cleanup;
> - }
> - (void)alarm(alarmtime);
> - }
> -#ifdef LARGE_FILE
> - if ((fd = open64(filename, O_CREAT | O_TRUNC | O_RDWR, 0664)) == -1) {
> -#else /* LARGE_FILE */
> - if ((fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0664)) == -1) {
> -#endif /* LARGE_FILE */
> - perror("open error");
> - anyfail();
> - }
> -
> - if ((buf = malloc(pagesize)) == NULL
> - || (pidarray = malloc(nprocs * sizeof(pid_t))) == NULL) {
> - perror("malloc error");
> - anyfail();
> - }
> -
> - for (i = 0; i < nprocs; i++)
> - *(pidarray + i) = 0;
> -
> - for (i = 0, data = 0; i < pagesize; i++) {
> - *(buf + i) = (data + pattern) & 0xff;
> - if (++data == nprocs)
> - data = 0;
> - }
> -#ifdef LARGE_FILE
> - if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
> -#else /* LARGE_FILE */
> - if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
> -#endif /* LARGE_FILE */
> - perror("lseek");
> - anyfail();
> - }
> - for (bytes_left = filesize; bytes_left; bytes_left -= c) {
> - write_cnt = MIN(pagesize, (int)bytes_left);
> - if ((c = write(fd, buf, write_cnt)) != write_cnt) {
> - if (c == -1) {
> - perror("write error");
> - } else {
> - (void)fprintf(stderr, "write: wrote %d of %d "
> - "bytes\n", c, write_cnt);
> - }
> - (void)close(fd);
> - (void)unlink(filename);
> - anyfail();
> - }
> + tst_res(TINFO, "creating file <%s> with %lld bytes, pattern %d",
> + TEST_FILE, filesize, pattern);
> }
> +}
>
> - (void)close(fd);
> -
> - /*
> - * Fork off mmap children.
> - */
> - for (procno = 0; procno < nprocs; procno++) {
> - switch (pid = fork()) {
> -
> - case -1:
> - perror("fork error");
> - goto cleanup;
> -
> - case 0:
> - child_mapper(filename, procno, nprocs);
> - exit(0);
> -
> - default:
> - pidarray[procno] = pid;
> - }
> - }
> -
> - /*
> - * Now wait for children and refork them as needed.
> - */
> -
> - while (!finished) {
> - pid = wait(&wait_stat);
> - /*
> - * Block signals while processing child exit.
> - */
> -
> - if (sighold(SIGALRM) || sighold(SIGINT)) {
> - perror("sighold error");
> - goto cleanup;
> - }
> -
> - if (pid != -1) {
> - /*
> - * Check exit status, then refork with the
> - * appropriate procno.
> - */
> - if (!WIFEXITED(wait_stat)
> - || WEXITSTATUS(wait_stat) != 0) {
> - (void)fprintf(stderr, "child exit with err "
> - "<x%x>\n", wait_stat);
> - goto cleanup;
> - }
> - for (i = 0; i < nprocs; i++)
> - if (pid == pidarray[i])
> - break;
> - if (i == nprocs) {
> - (void)fprintf(stderr, "unknown child pid %d, "
> - "<x%x>\n", pid, wait_stat);
> - goto cleanup;
> - }
> -
> - if ((pid = fork()) == -1) {
> - perror("fork error");
> - pidarray[i] = 0;
> - goto cleanup;
> - } else if (pid == 0) { /* child */
> - child_mapper(filename, i, nprocs);
> - exit(0);
> - } else
> - pidarray[i] = pid;
> - } else {
> - /*
> - * wait returned an error. If EINTR, then
> - * normal finish, else it's an unexpected
> - * error...
> - */
> - if (errno != EINTR || !finished) {
> - perror("unexpected wait error");
> - goto cleanup;
> - }
> - }
> - if (sigrelse(SIGALRM) || sigrelse(SIGINT)) {
> - perror("sigrelse error");
> - goto cleanup;
> - }
> - }
> -
> - /*
> - * Finished! Check the file for sanity, then kill all
> - * the children and done!.
> - */
> -
> - if (sighold(SIGALRM)) {
> - perror("sighold error");
> - goto cleanup;
> - }
> - (void)alarm(0);
> - no_prob = 1;
> -
> -cleanup:
> - for (i = 0; i < nprocs; i++)
> - (void)kill(pidarray[i], SIGKILL);
> -
> - while (wait(&wait_stat) != -1 || errno != ECHILD)
> - continue;
> -
> - if (no_prob) { /* only check file if no errors */
> - if (!fileokay(filename, buf)) {
> - (void)fprintf(stderr, "file data incorrect!\n");
> - (void)printf(" leaving file <%s>\n", filename);
> - /***** LTP Port *****/
> - local_flag = FAILED;
> - anyfail();
> - /***** ** *****/
> - } else {
> - (void)printf("file data okay\n");
> - if (!leavefile)
> - (void)unlink(filename);
> - }
> - } else
> - (void)printf(" leaving file <%s>\n", filename);
> -
> - (void)time(&t);
> - //(void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port
> - ok_exit();
> - tst_exit();
> +static void cleanup(void)
> +{
> + if (fd > 0)
> + SAFE_CLOSE(fd);
> }
>
> /*
> @@ -454,91 +121,51 @@ cleanup:
> * determined based on nprocs & procno). After a specific number of
> * iterations, it exits.
> */
> -void child_mapper(char *file, unsigned procno, unsigned nprocs)
> +static void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
> {
> -#ifdef LARGE_FILE
> - struct stat64 statbuf;
> - off64_t filesize;
> - off64_t offset;
> -#else /* LARGE_FILE */
> struct stat statbuf;
> off_t filesize;
> off_t offset;
> -#endif /* LARGE_FILE */
> size_t validsize;
> size_t mapsize;
> char *maddr = NULL, *paddr;
> - int fd;
> - size_t pagesize = sysconf(_SC_PAGE_SIZE);
> - unsigned randpage;
> + unsigned int randpage;
> unsigned int seed;
> - unsigned loopcnt;
> - unsigned nloops;
> - unsigned mappages;
> - unsigned i;
> + unsigned int loopcnt;
> + unsigned int nloops;
> + unsigned int mappages;
> + unsigned int i;
>
> seed = initrand(); /* initialize random seed */
>
> -#ifdef LARGE_FILE
> - if (stat64(file, &statbuf) == -1) {
> -#else /* LARGE_FILE */
> - if (stat(file, &statbuf) == -1) {
> -#endif /* LARGE_FILE */
> - perror("stat error");
> - anyfail();
> - }
> + SAFE_STAT(file, &statbuf);
> filesize = statbuf.st_size;
>
> -#ifdef LARGE_FILE
> - if ((fd = open64(file, O_RDWR)) == -1) {
> -#else /* LARGE_FILE */
> - if ((fd = open(file, O_RDWR)) == -1) {
> -#endif /* LARGE_FILE */
> - perror("open error");
> - anyfail();
> - }
> + fd = SAFE_OPEN(file, O_RDWR);
>
> - if (statbuf.st_size - sparseoffset > SIZE_MAX) {
> - fprintf(stderr, "size_t overflow when setting up map\n");
> - anyfail();
> - }
> + if (statbuf.st_size - sparseoffset > UINT_MAX)
> + tst_brk(TBROK, "size_t overflow when setting up map");
> mapsize = (size_t) (statbuf.st_size - sparseoffset);
> mappages = roundup(mapsize, pagesize) / pagesize;
> offset = sparseoffset;
> if (do_offset) {
> int pageoffset = lrand48() % mappages;
> int byteoffset = pageoffset * pagesize;
> +
> offset += byteoffset;
> mapsize -= byteoffset;
> mappages -= pageoffset;
> }
> nloops = (randloops) ? (lrand48() % MAXLOOPS) : MAXLOOPS;
>
> - if (debug) {
> -#ifdef LARGE_FILE
> - (void)printf("child %d (pid %ld): seed %d, fsize %Ld, "
> - "mapsize %d, off %Ld, loop %d\n",
> - procno, getpid(), seed, filesize, mapsize,
> - offset / pagesize, nloops);
> -#else /* LARGE_FILE */
> - (void)printf("child %d (pid %d): seed %d, fsize %ld, "
> - "mapsize %ld, off %ld, loop %d\n",
> - procno, getpid(), seed, filesize, (long)mapsize,
> - offset / pagesize, nloops);
> -#endif /* LARGE_FILE */
> - }
> -#ifdef LARGE_FILE
> - if ((maddr = mmap64(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED,
> - fd, offset)) == (caddr_t) - 1) {
> -#else /* LARGE_FILE */
> - if ((maddr = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED,
> - fd, offset)) == (caddr_t) - 1) {
> -#endif /* LARGE_FILE */
> - perror("mmap error");
> - anyfail();
> - }
> + if (debug)
> + tst_res(TINFO, "child %d (pid %d): seed %d, fsize %lld, mapsize %ld, off %lld, loop %d",
> + procno, getpid(), seed, (long long)filesize,
> + (long)mapsize, (long long)offset / pagesize,
> nloops);
We should at least print the seed value for the purposes of bug
reproduction. Or just use a static pattern.
>
> - (void)close(fd);
> + maddr = SAFE_MMAP(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
> + offset);
> + SAFE_CLOSE(fd);
>
> /*
> * Now loop read/writing random pages.
> @@ -554,15 +181,11 @@ void child_mapper(char *file, unsigned procno, unsigned nprocs)
>
> for (i = procno; i < validsize; i += nprocs) {
> if (*((unsigned char *)(paddr + i))
> - != ((procno + pattern) & 0xff)) {
> - (void)fprintf(stderr, "child %d: invalid data "
> - "<x%x>", procno,
> - *((unsigned char *)(paddr + i)));
> - (void)fprintf(stderr, " at pg %d off %d, exp "
> - "<x%x>\n", randpage, i,
> - (procno + pattern) & 0xff);
> - anyfail();
> - }
> + != ((procno + pattern) & 0xff))
> + tst_brk(TFAIL, "child %d: invalid data <x%x>\n"
> + " at pg %d off %d, exp <x%x>", procno,
> + *((unsigned char *)(paddr + i)),
> + randpage, i, (procno + pattern) & 0xff);
>
> /*
> * Now write it.
> @@ -570,139 +193,74 @@ void child_mapper(char *file, unsigned procno, unsigned nprocs)
> *(paddr + i) = (procno + pattern) & 0xff;
> }
> }
> - if (dosync) {
> + if (do_sync) {
> /*
> * Exercise msync() as well!
> */
> randpage = lrand48() % mappages;
> paddr = maddr + (randpage * pagesize); /* page address */
> if (msync(paddr, (mappages - randpage) * pagesize,
> - MS_SYNC) == -1) {
> - anyfail();
> - }
> - }
> - if (munmap(maddr, mapsize) == -1) {
> - perror("munmap failed");
> - local_flag = FAILED;
> - anyfail();
> + MS_SYNC) == -1)
> + tst_brk(TBROK | TERRNO, "msync failed");
> }
> + SAFE_MUNMAP(maddr, mapsize);
> exit(0);
> }
>
> /*
> * Make sure file has all the correct data.
> */
> -int fileokay(char *file, uchar_t * expbuf)
> +static void fileokay(char *file, unsigned char *expbuf)
> {
> -#ifdef LARGE_FILE
> - struct stat64 statbuf;
> -#else /* LARGE_FILE */
> - struct stat statbuf;
> -#endif /* LARGE_FILE */
> - size_t mapsize;
> - unsigned mappages;
> - unsigned pagesize = sysconf(_SC_PAGE_SIZE);
> - uchar_t readbuf[pagesize];
> - int fd;
> int cnt;
> - unsigned i, j;
> -
> -#ifdef LARGE_FILE
> - if ((fd = open64(file, O_RDONLY)) == -1) {
> -#else /* LARGE_FILE */
> - if ((fd = open(file, O_RDONLY)) == -1) {
> -#endif /* LARGE_FILE */
> - perror("open error");
> - /***** LTP Port *****/
> - local_flag = FAILED;
> - anyfail();
> - /***** ** *****/
> - return 0;
> - }
> -#ifdef LARGE_FILE
> - if (fstat64(fd, &statbuf) == -1) {
> -#else /* LARGE_FILE */
> - if (fstat(fd, &statbuf) == -1) {
> -#endif /* LARGE_FILE */
> - perror("stat error");
> - /***** LTP Port *****/
> - local_flag = FAILED;
> - anyfail();
> - /***** ** *****/
> - return 0;
> - }
> -#ifdef LARGE_FILE
> - if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
> -#else /* LARGE_FILE */
> - if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
> -#endif /* LARGE_FILE */
> - perror("lseek");
> - anyfail();
> - }
> + size_t mapsize;
> + struct stat statbuf;
> + unsigned char readbuf[pagesize];
> + unsigned int i, j;
> + unsigned int mappages;
> + unsigned int pagesize = sysconf(_SC_PAGE_SIZE);
We seem to be redefining pagesize here. It seems sysconf(_SC_PAGE_SIZE)
is called 3 times.
>
> - if (statbuf.st_size - sparseoffset > SIZE_MAX) {
> - fprintf(stderr, "size_t overflow when setting up map\n");
> - anyfail();
> - }
> + fd = SAFE_OPEN(file, O_RDONLY);
> +
> + SAFE_FSTAT(fd, &statbuf);
> + SAFE_LSEEK(fd, sparseoffset, SEEK_SET);
> +
> + if (statbuf.st_size - sparseoffset > UINT_MAX)
> + tst_brk(TBROK, "size_t overflow when setting up map");
> mapsize = (size_t) (statbuf.st_size - sparseoffset);
>
> mappages = roundup(mapsize, pagesize) / pagesize;
>
> for (i = 0; i < mappages; i++) {
> - cnt = read(fd, readbuf, pagesize);
> - if (cnt == -1) {
> - perror("read error");
> - /***** LTP Port *****/
> - local_flag = FAILED;
> - anyfail();
> - /***** ** *****/
> - return 0;
> - } else if (cnt != pagesize) {
> + cnt = SAFE_READ(0, fd, readbuf, pagesize);
> + if ((unsigned int)cnt != pagesize) {
> /*
> * Okay if at last page in file...
> */
> - if ((i * pagesize) + cnt != mapsize) {
> - (void)fprintf(stderr, "read %d of %ld bytes\n",
> - (i * pagesize) + cnt,
> - (long)mapsize);
> - close(fd);
> - return 0;
> - }
> + if ((i * pagesize) + cnt != mapsize)
> + tst_brk(TFAIL, "missing data: read %d of %ld bytes",
> + (i * pagesize) + cnt, (long)mapsize);
> }
> /*
> * Compare read bytes of data.
> */
> - for (j = 0; j < cnt; j++) {
> - if (expbuf[j] != readbuf[j]) {
> - (void)fprintf(stderr,
> - "read bad data: exp %c got %c)",
> - expbuf[j], readbuf[j]);
> -#ifdef LARGE_FILE
> - (void)fprintf(stderr, ", pg %d off %d, "
> - "(fsize %Ld)\n", i, j,
> - statbuf.st_size);
> -#else /* LARGE_FILE */
> - (void)fprintf(stderr, ", pg %d off %d, "
> - "(fsize %ld)\n", i, j,
> - statbuf.st_size);
> -#endif /* LARGE_FILE */
> - close(fd);
> - return 0;
> - }
> + for (j = 0; j < (unsigned int)cnt; j++) {
> + if (expbuf[j] != readbuf[j])
> + tst_brk(TFAIL,
> + "read bad data: exp %c got %c, pg %d off %d, (fsize %lld)",
> + expbuf[j], readbuf[j], i, j,
> + (long long)statbuf.st_size);
> }
> }
> - close(fd);
> -
> - return 1;
> + SAFE_CLOSE(fd);
> }
>
> - /*ARGSUSED*/ void finish(int sig)
> +static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
> {
> finished++;
> - return;
> }
>
> -unsigned int initrand(void)
> +static unsigned int initrand(void)
> {
> unsigned int seed;
>
> @@ -718,21 +276,147 @@ unsigned int initrand(void)
> seed = rand();
> srand((unsigned int)time(NULL));
> seed = (seed ^ rand()) % 100000;
> - srand48((long int)seed);
> - return (seed);
> + srand48((long)seed);
> + return seed;
> }
>
> -/***** LTP Port *****/
> -void ok_exit(void)
> +static void run(void)
> {
> - tst_resm(TPASS, "Test passed");
> - tst_rmdir();
> - tst_exit();
> -}
> + int c;
> + int i;
> + int procno;
> + int wait_stat;
> + off_t bytes_left;
> + pid_t pid;
> + pid_t *pidarray = NULL;
> + sigset_t set_mask;
> + size_t write_cnt;
> + struct sigaction sa;
> + unsigned char data;
> + unsigned char *buf;
> + unsigned int seed;
>
> -int anyfail(void)
> -{
> - tst_brkm(TFAIL, tst_rmdir, "Test failed");
> + pagesize = sysconf(_SC_PAGE_SIZE);
> + seed = initrand();
> + pattern = seed & 0xff;
> +
> + /*
> + * Plan for death by signal or alarm.
> + * Also catch and cleanup with SIGINT.
> + */
> + sa.sa_handler = sighandler;
> + sa.sa_flags = 0;
> + SAFE_SIGEMPTYSET(&sa.sa_mask);
> + SAFE_SIGACTION(SIGINT, &sa, 0);
> + SAFE_SIGACTION(SIGQUIT, &sa, 0);
> + SAFE_SIGACTION(SIGTERM, &sa, 0);
> +
> + SAFE_SIGACTION(SIGALRM, &sa, 0);
> + alarm(tst_remaining_runtime());
> +
> + fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, 0664);
> +
> + buf = SAFE_MALLOC(pagesize);
> + pidarray = SAFE_MALLOC(nprocs * sizeof(pid_t));
> +
> + for (i = 0; i < nprocs; i++)
> + *(pidarray + i) = 0;
> +
> + for (i = 0, data = 0; i < (int)pagesize; i++) {
> + *(buf + i) = (data + pattern) & 0xff;
> + if (++data == nprocs)
> + data = 0;
> + }
> + SAFE_LSEEK(fd, (off_t)sparseoffset, SEEK_SET);
> + for (bytes_left = filesize; bytes_left; bytes_left -= c) {
> + write_cnt = MIN((long long)pagesize, (long long)bytes_left);
> + c = SAFE_WRITE(1, fd, buf, write_cnt);
> + }
> + SAFE_CLOSE(fd);
> +
> + /*
> + * Fork off mmap children.
> + */
> + for (procno = 0; procno < nprocs; procno++) {
> + switch (pid = SAFE_FORK()) {
> + case 0:
> + child_mapper(TEST_FILE, (unsigned int)procno, (unsigned int)nprocs);
> + exit(0);
> +
> + default:
> + pidarray[procno] = pid;
> + }
> + }
> +
> + /*
> + * Now wait for children and refork them as needed.
> + */
> +
> + SAFE_SIGEMPTYSET(&set_mask);
> + SAFE_SIGADDSET(&set_mask, SIGALRM);
> + SAFE_SIGADDSET(&set_mask, SIGINT);
> + while (!finished) {
> + pid = wait(&wait_stat);
> + /*
> + * Block signals while processing child exit.
> + */
> +
> + SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
> +
> + if (pid != -1) {
> + /*
> + * Check exit status, then refork with the
> + * appropriate procno.
> + */
> + if (!WIFEXITED(wait_stat)
> + || WEXITSTATUS(wait_stat) != 0)
> + tst_brk(TBROK, "child exit with err <x%x>",
> + wait_stat);
> + for (i = 0; i < nprocs; i++)
> + if (pid == pidarray[i])
> + break;
> + if (i == nprocs)
> + tst_brk(TBROK, "unknown child pid %d, <x%x>",
> + pid, wait_stat);
> +
> + pid = SAFE_FORK();
> + if (pid == 0) { /* child */
> + child_mapper(TEST_FILE, (unsigned int)i, (unsigned int)nprocs);
> + exit(0);
> + } else {
> + pidarray[i] = pid;
> + }
> + } else {
> + /*
> + * wait returned an error. If EINTR, then
> + * normal finish, else it's an unexpected
> + * error...
> + */
> + if (errno != EINTR || !finished)
> + tst_brk(TBROK | TERRNO,
> + "unexpected wait error");
> + }
> + SAFE_SIGPROCMASK(SIG_UNBLOCK, &set_mask, NULL);
> + }
> +
> + SAFE_SIGEMPTYSET(&set_mask);
> + SAFE_SIGADDSET(&set_mask, SIGALRM);
> + SAFE_SIGPROCMASK(SIG_BLOCK, &set_mask, NULL);
> + alarm(0);
> +
> + /*
> + * Finished! Check the file for sanity.
> + */
This comment (and similar) can go as well.
> + fileokay(TEST_FILE, buf);
> + tst_res(TPASS, "file has expected data");
> }
>
> -/***** ** ** *****/
> +static struct tst_test test = {
> + .test_all = run,
> + .setup = setup,
> + .options = options,
> + .cleanup = cleanup,
> + .max_runtime = 12,
> + .needs_tmpdir = 1,
> + .forks_child = 1,
> +};
> --
> 2.38.0.rc1.362.ged0d419d3c-goog
--
Thank you,
Richard.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-10-18 10:16 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-12 14:48 [LTP] [PATCH v5 0/5] mmapstress01: refactor to ltp framework Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 1/5] mmapstress01: refactor to tst_test framework Edward Liaw via ltp
2022-10-18 9:42 ` Richard Palethorpe
2022-10-12 14:48 ` [LTP] [PATCH v5 2/5] mmapstress01: format comments Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 3/5] mmapstress01: define fsize bounds by file offset bits Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 4/5] mmapstress01: remove unnecessary pidarray Edward Liaw via ltp
2022-10-12 14:48 ` [LTP] [PATCH v5 5/5] mmapstress01: move sighandler to setup and remove sig blocks Edward Liaw via ltp
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox