1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2003
4f08c3bdfSopenharmony_ci * 01/02/2003	Port to LTP avenkat@us.ibm.com
5f08c3bdfSopenharmony_ci * 06/30/2001	Port to Linux	nsharoff@us.ibm.com
6f08c3bdfSopenharmony_ci * 10/03/2022	Refactor to LTP framework	edliaw@google.com
7f08c3bdfSopenharmony_ci */
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci * This test stresses mmaps, without dealing with fragments or anything!
11f08c3bdfSopenharmony_ci * It forks a specified number of children,
12f08c3bdfSopenharmony_ci * all of whom mmap the same file, make a given number of accesses
13f08c3bdfSopenharmony_ci * to random pages in the map (reading & writing and comparing data).
14f08c3bdfSopenharmony_ci * Then the child exits and the parent forks another to take its place.
15f08c3bdfSopenharmony_ci * Each time a child is forked, it stats the file and maps the full
16f08c3bdfSopenharmony_ci * length of the file.
17f08c3bdfSopenharmony_ci *
18f08c3bdfSopenharmony_ci * This program continues to run until it either receives a SIGINT,
19f08c3bdfSopenharmony_ci * or times out (if a timeout value is specified).  When either of
20f08c3bdfSopenharmony_ci * these things happens, it cleans up its kids, then checks the
21f08c3bdfSopenharmony_ci * file to make sure it has the correct data.
22f08c3bdfSopenharmony_ci */
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_ci#define _GNU_SOURCE 1
25f08c3bdfSopenharmony_ci#include <stdio.h>
26f08c3bdfSopenharmony_ci#include <fcntl.h>
27f08c3bdfSopenharmony_ci#include <signal.h>
28f08c3bdfSopenharmony_ci#include <sys/mman.h>
29f08c3bdfSopenharmony_ci#include <sys/wait.h>
30f08c3bdfSopenharmony_ci#include <sys/stat.h>
31f08c3bdfSopenharmony_ci#include <unistd.h>
32f08c3bdfSopenharmony_ci#include <stdlib.h>
33f08c3bdfSopenharmony_ci#include <errno.h>
34f08c3bdfSopenharmony_ci#include <sys/types.h>
35f08c3bdfSopenharmony_ci#include <limits.h>
36f08c3bdfSopenharmony_ci#include <float.h>
37f08c3bdfSopenharmony_ci#include "tst_test.h"
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci#if _FILE_OFFSET_BITS == 64
40f08c3bdfSopenharmony_ci# define FSIZE_MIN LONG_MIN
41f08c3bdfSopenharmony_ci# define FSIZE_MAX LONG_MAX
42f08c3bdfSopenharmony_ci#else
43f08c3bdfSopenharmony_ci# define FSIZE_MIN INT_MIN
44f08c3bdfSopenharmony_ci# define FSIZE_MAX INT_MAX
45f08c3bdfSopenharmony_ci#endif
46f08c3bdfSopenharmony_ci#define MAXLOOPS	500	/* max pages for map children to write */
47f08c3bdfSopenharmony_ci#define TEST_FILE	"mmapstress01.out"
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci#ifdef roundup
50f08c3bdfSopenharmony_ci#undef roundup
51f08c3bdfSopenharmony_ci#endif
52f08c3bdfSopenharmony_ci#define roundup(x, y)	((((x)+((y)-1))/(y))*(y))
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cistatic unsigned int initrand(void);
55f08c3bdfSopenharmony_cistatic void sighandler(int);
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_cistatic char *debug;
58f08c3bdfSopenharmony_cistatic char *do_sync;
59f08c3bdfSopenharmony_cistatic char *do_offset;
60f08c3bdfSopenharmony_cistatic char *opt_filesize;
61f08c3bdfSopenharmony_cistatic char *opt_nprocs;
62f08c3bdfSopenharmony_cistatic char *opt_pattern;
63f08c3bdfSopenharmony_cistatic char *opt_sparseoffset;
64f08c3bdfSopenharmony_cistatic char *randloops;
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_cistatic int fd;
67f08c3bdfSopenharmony_cistatic volatile int finished;
68f08c3bdfSopenharmony_cistatic int nprocs;
69f08c3bdfSopenharmony_cistatic long long filesize = 4096;
70f08c3bdfSopenharmony_cistatic long long sparseoffset;
71f08c3bdfSopenharmony_cistatic size_t pagesize;
72f08c3bdfSopenharmony_cistatic int pattern;
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_cistatic void setup(void)
75f08c3bdfSopenharmony_ci{
76f08c3bdfSopenharmony_ci	struct sigaction sa;
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	sa.sa_handler = sighandler;
79f08c3bdfSopenharmony_ci	sa.sa_flags = 0;
80f08c3bdfSopenharmony_ci	SAFE_SIGEMPTYSET(&sa.sa_mask);
81f08c3bdfSopenharmony_ci	SAFE_SIGACTION(SIGINT, &sa, 0);
82f08c3bdfSopenharmony_ci	SAFE_SIGACTION(SIGQUIT, &sa, 0);
83f08c3bdfSopenharmony_ci	SAFE_SIGACTION(SIGTERM, &sa, 0);
84f08c3bdfSopenharmony_ci	SAFE_SIGACTION(SIGALRM, &sa, 0);
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	pagesize = sysconf(_SC_PAGE_SIZE);
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci	if (tst_parse_filesize(opt_filesize, &filesize, 0, FSIZE_MAX))
89f08c3bdfSopenharmony_ci		tst_brk(TBROK, "invalid initial filesize '%s'", opt_filesize);
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	if (tst_parse_filesize(opt_sparseoffset, &sparseoffset, FSIZE_MIN, FSIZE_MAX))
92f08c3bdfSopenharmony_ci		tst_brk(TBROK, "invalid sparse offset '%s'", opt_sparseoffset);
93f08c3bdfSopenharmony_ci	if (sparseoffset % pagesize != 0)
94f08c3bdfSopenharmony_ci		tst_brk(TBROK, "sparseoffset must be pagesize multiple");
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	if (tst_parse_int(opt_nprocs, &nprocs, 0, 255))
97f08c3bdfSopenharmony_ci		tst_brk(TBROK, "invalid number of mapping children '%s'",
98f08c3bdfSopenharmony_ci			opt_nprocs);
99f08c3bdfSopenharmony_ci	if (!opt_nprocs)
100f08c3bdfSopenharmony_ci		nprocs = MAX(MIN(tst_ncpus() - 1L, 20L), 1L);
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ci	if (tst_parse_int(opt_pattern, &pattern, 0, 255))
103f08c3bdfSopenharmony_ci		tst_brk(TBROK, "invalid pattern '%s'", opt_pattern);
104f08c3bdfSopenharmony_ci	if (!opt_pattern)
105f08c3bdfSopenharmony_ci		pattern = initrand() & 0xff;
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	tst_res(TINFO, "creating file <%s> with %lld bytes, pattern %d",
108f08c3bdfSopenharmony_ci		TEST_FILE, filesize, pattern);
109f08c3bdfSopenharmony_ci}
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_cistatic void cleanup(void)
112f08c3bdfSopenharmony_ci{
113f08c3bdfSopenharmony_ci	if (fd > 0)
114f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd);
115f08c3bdfSopenharmony_ci}
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci/*
118f08c3bdfSopenharmony_ci * Child process that reads/writes map.  The child stats the file
119f08c3bdfSopenharmony_ci * to determine the size, maps the size of the file, then reads/writes
120f08c3bdfSopenharmony_ci * its own locations on random pages of the map (its locations being
121f08c3bdfSopenharmony_ci * determined based on nprocs & procno).  After a specific number of
122f08c3bdfSopenharmony_ci * iterations, it exits.
123f08c3bdfSopenharmony_ci */
124f08c3bdfSopenharmony_cistatic void child_mapper(char *file, unsigned int procno, unsigned int nprocs)
125f08c3bdfSopenharmony_ci{
126f08c3bdfSopenharmony_ci	struct stat statbuf;
127f08c3bdfSopenharmony_ci	off_t filesize;
128f08c3bdfSopenharmony_ci	off_t offset;
129f08c3bdfSopenharmony_ci	size_t validsize;
130f08c3bdfSopenharmony_ci	size_t mapsize;
131f08c3bdfSopenharmony_ci	char *maddr = NULL, *paddr;
132f08c3bdfSopenharmony_ci	unsigned int randpage;
133f08c3bdfSopenharmony_ci	unsigned int seed;
134f08c3bdfSopenharmony_ci	unsigned int loopcnt;
135f08c3bdfSopenharmony_ci	unsigned int nloops;
136f08c3bdfSopenharmony_ci	unsigned int mappages;
137f08c3bdfSopenharmony_ci	unsigned int i;
138f08c3bdfSopenharmony_ci
139f08c3bdfSopenharmony_ci	seed = initrand();
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci	SAFE_STAT(file, &statbuf);
142f08c3bdfSopenharmony_ci	filesize = statbuf.st_size;
143f08c3bdfSopenharmony_ci
144f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(file, O_RDWR);
145f08c3bdfSopenharmony_ci
146f08c3bdfSopenharmony_ci	if (statbuf.st_size - sparseoffset > UINT_MAX)
147f08c3bdfSopenharmony_ci		tst_brk(TBROK, "size_t overflow when setting up map");
148f08c3bdfSopenharmony_ci	mapsize = (size_t) (statbuf.st_size - sparseoffset);
149f08c3bdfSopenharmony_ci	mappages = roundup(mapsize, pagesize) / pagesize;
150f08c3bdfSopenharmony_ci	offset = sparseoffset;
151f08c3bdfSopenharmony_ci	if (do_offset) {
152f08c3bdfSopenharmony_ci		int pageoffset = lrand48() % mappages;
153f08c3bdfSopenharmony_ci		int byteoffset = pageoffset * pagesize;
154f08c3bdfSopenharmony_ci
155f08c3bdfSopenharmony_ci		offset += byteoffset;
156f08c3bdfSopenharmony_ci		mapsize -= byteoffset;
157f08c3bdfSopenharmony_ci		mappages -= pageoffset;
158f08c3bdfSopenharmony_ci	}
159f08c3bdfSopenharmony_ci	nloops = (randloops) ? (lrand48() % MAXLOOPS) : MAXLOOPS;
160f08c3bdfSopenharmony_ci
161f08c3bdfSopenharmony_ci	if (debug)
162f08c3bdfSopenharmony_ci		tst_res(TINFO, "child %d (pid %d): seed %d, fsize %lld, mapsize %ld, off %lld, loop %d",
163f08c3bdfSopenharmony_ci			procno, getpid(), seed, (long long)filesize,
164f08c3bdfSopenharmony_ci			(long)mapsize, (long long)offset / pagesize, nloops);
165f08c3bdfSopenharmony_ci
166f08c3bdfSopenharmony_ci	maddr = SAFE_MMAP(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
167f08c3bdfSopenharmony_ci			  offset);
168f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
169f08c3bdfSopenharmony_ci
170f08c3bdfSopenharmony_ci	for (loopcnt = 0; loopcnt < nloops; loopcnt++) {
171f08c3bdfSopenharmony_ci		randpage = lrand48() % mappages;
172f08c3bdfSopenharmony_ci		paddr = maddr + (randpage * pagesize);	/* page address */
173f08c3bdfSopenharmony_ci
174f08c3bdfSopenharmony_ci		if (randpage < mappages - 1 || !(mapsize % pagesize))
175f08c3bdfSopenharmony_ci			validsize = pagesize;
176f08c3bdfSopenharmony_ci		else
177f08c3bdfSopenharmony_ci			validsize = mapsize % pagesize;
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ci		for (i = procno; i < validsize; i += nprocs) {
180f08c3bdfSopenharmony_ci			if (*((unsigned char *)(paddr + i))
181f08c3bdfSopenharmony_ci			    != ((procno + pattern) & 0xff))
182f08c3bdfSopenharmony_ci				tst_brk(TFAIL, "child %d: invalid data <x%x>\n"
183f08c3bdfSopenharmony_ci					" at pg %d off %d, exp <x%x>", procno,
184f08c3bdfSopenharmony_ci					*((unsigned char *)(paddr + i)),
185f08c3bdfSopenharmony_ci					randpage, i, (procno + pattern) & 0xff);
186f08c3bdfSopenharmony_ci
187f08c3bdfSopenharmony_ci			*(paddr + i) = (procno + pattern) & 0xff;
188f08c3bdfSopenharmony_ci		}
189f08c3bdfSopenharmony_ci	}
190f08c3bdfSopenharmony_ci	if (do_sync) {
191f08c3bdfSopenharmony_ci		randpage = lrand48() % mappages;
192f08c3bdfSopenharmony_ci		paddr = maddr + (randpage * pagesize);	/* page address */
193f08c3bdfSopenharmony_ci		if (msync(paddr, (mappages - randpage) * pagesize,
194f08c3bdfSopenharmony_ci			  MS_SYNC) == -1)
195f08c3bdfSopenharmony_ci			tst_brk(TBROK | TERRNO, "msync failed");
196f08c3bdfSopenharmony_ci	}
197f08c3bdfSopenharmony_ci	SAFE_MUNMAP(maddr, mapsize);
198f08c3bdfSopenharmony_ci	exit(0);
199f08c3bdfSopenharmony_ci}
200f08c3bdfSopenharmony_ci
201f08c3bdfSopenharmony_ci/* Make sure file has all the correct data. */
202f08c3bdfSopenharmony_cistatic void fileokay(char *file, unsigned char *expbuf)
203f08c3bdfSopenharmony_ci{
204f08c3bdfSopenharmony_ci	int cnt;
205f08c3bdfSopenharmony_ci	size_t mapsize;
206f08c3bdfSopenharmony_ci	struct stat statbuf;
207f08c3bdfSopenharmony_ci	unsigned char readbuf[pagesize];
208f08c3bdfSopenharmony_ci	unsigned int i, j;
209f08c3bdfSopenharmony_ci	unsigned int mappages;
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(file, O_RDONLY);
212f08c3bdfSopenharmony_ci
213f08c3bdfSopenharmony_ci	SAFE_FSTAT(fd, &statbuf);
214f08c3bdfSopenharmony_ci	SAFE_LSEEK(fd, sparseoffset, SEEK_SET);
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	if (statbuf.st_size - sparseoffset > UINT_MAX)
217f08c3bdfSopenharmony_ci		tst_brk(TBROK, "size_t overflow when setting up map");
218f08c3bdfSopenharmony_ci	mapsize = (size_t) (statbuf.st_size - sparseoffset);
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	mappages = roundup(mapsize, pagesize) / pagesize;
221f08c3bdfSopenharmony_ci
222f08c3bdfSopenharmony_ci	for (i = 0; i < mappages; i++) {
223f08c3bdfSopenharmony_ci		cnt = SAFE_READ(0, fd, readbuf, pagesize);
224f08c3bdfSopenharmony_ci		if ((unsigned int)cnt != pagesize) {
225f08c3bdfSopenharmony_ci			/* Okay if at last page in file... */
226f08c3bdfSopenharmony_ci			if ((i * pagesize) + cnt != mapsize)
227f08c3bdfSopenharmony_ci				tst_brk(TFAIL, "missing data: read %lu of %ld bytes",
228f08c3bdfSopenharmony_ci					(i * pagesize) + cnt, (long)mapsize);
229f08c3bdfSopenharmony_ci		}
230f08c3bdfSopenharmony_ci		/* Compare read bytes of data. */
231f08c3bdfSopenharmony_ci		for (j = 0; j < (unsigned int)cnt; j++) {
232f08c3bdfSopenharmony_ci			if (expbuf[j] != readbuf[j])
233f08c3bdfSopenharmony_ci				tst_brk(TFAIL,
234f08c3bdfSopenharmony_ci					"read bad data: exp %c got %c, pg %d off %d, (fsize %lld)",
235f08c3bdfSopenharmony_ci					expbuf[j], readbuf[j], i, j,
236f08c3bdfSopenharmony_ci					(long long)statbuf.st_size);
237f08c3bdfSopenharmony_ci		}
238f08c3bdfSopenharmony_ci	}
239f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
240f08c3bdfSopenharmony_ci}
241f08c3bdfSopenharmony_ci
242f08c3bdfSopenharmony_cistatic void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
243f08c3bdfSopenharmony_ci{
244f08c3bdfSopenharmony_ci	finished++;
245f08c3bdfSopenharmony_ci}
246f08c3bdfSopenharmony_ci
247f08c3bdfSopenharmony_cistatic unsigned int initrand(void)
248f08c3bdfSopenharmony_ci{
249f08c3bdfSopenharmony_ci	unsigned int seed;
250f08c3bdfSopenharmony_ci
251f08c3bdfSopenharmony_ci	/*
252f08c3bdfSopenharmony_ci	 * Use srand/rand to diffuse the information from the
253f08c3bdfSopenharmony_ci	 * time and pid.  If you start several processes, then
254f08c3bdfSopenharmony_ci	 * the time and pid information don't provide much
255f08c3bdfSopenharmony_ci	 * variation.
256f08c3bdfSopenharmony_ci	 */
257f08c3bdfSopenharmony_ci	srand((unsigned int)getpid());
258f08c3bdfSopenharmony_ci	seed = rand();
259f08c3bdfSopenharmony_ci	srand((unsigned int)time(NULL));
260f08c3bdfSopenharmony_ci	seed = (seed ^ rand()) % 100000;
261f08c3bdfSopenharmony_ci	srand48((long)seed);
262f08c3bdfSopenharmony_ci	return seed;
263f08c3bdfSopenharmony_ci}
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_cistatic void run(void)
266f08c3bdfSopenharmony_ci{
267f08c3bdfSopenharmony_ci	int c;
268f08c3bdfSopenharmony_ci	int i;
269f08c3bdfSopenharmony_ci	int wait_stat;
270f08c3bdfSopenharmony_ci	off_t bytes_left;
271f08c3bdfSopenharmony_ci	pid_t pid;
272f08c3bdfSopenharmony_ci	pid_t *pidarray;
273f08c3bdfSopenharmony_ci	size_t write_cnt;
274f08c3bdfSopenharmony_ci	unsigned char data;
275f08c3bdfSopenharmony_ci	unsigned char *buf;
276f08c3bdfSopenharmony_ci
277f08c3bdfSopenharmony_ci	alarm(tst_remaining_runtime());
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci	finished = 0;
280f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, 0664);
281f08c3bdfSopenharmony_ci	buf = SAFE_MALLOC(pagesize);
282f08c3bdfSopenharmony_ci	pidarray = SAFE_MALLOC(nprocs * sizeof(pid_t));
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci	for (i = 0; i < nprocs; i++)
285f08c3bdfSopenharmony_ci		*(pidarray + i) = 0;
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci	for (i = 0, data = 0; i < (int)pagesize; i++) {
288f08c3bdfSopenharmony_ci		*(buf + i) = (data + pattern) & 0xff;
289f08c3bdfSopenharmony_ci		if (++data == nprocs)
290f08c3bdfSopenharmony_ci			data = 0;
291f08c3bdfSopenharmony_ci	}
292f08c3bdfSopenharmony_ci	SAFE_LSEEK(fd, (off_t)sparseoffset, SEEK_SET);
293f08c3bdfSopenharmony_ci	for (bytes_left = filesize; bytes_left; bytes_left -= c) {
294f08c3bdfSopenharmony_ci		write_cnt = MIN((long long)pagesize, (long long)bytes_left);
295f08c3bdfSopenharmony_ci		c = SAFE_WRITE(1, fd, buf, write_cnt);
296f08c3bdfSopenharmony_ci	}
297f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
298f08c3bdfSopenharmony_ci
299f08c3bdfSopenharmony_ci	for (i = 0; i < nprocs; i++) {
300f08c3bdfSopenharmony_ci		pid = SAFE_FORK();
301f08c3bdfSopenharmony_ci
302f08c3bdfSopenharmony_ci		if (pid == 0) {
303f08c3bdfSopenharmony_ci			child_mapper(TEST_FILE, (unsigned int)i, (unsigned int)nprocs);
304f08c3bdfSopenharmony_ci			exit(0);
305f08c3bdfSopenharmony_ci		} else {
306f08c3bdfSopenharmony_ci			pidarray[i] = pid;
307f08c3bdfSopenharmony_ci		}
308f08c3bdfSopenharmony_ci	}
309f08c3bdfSopenharmony_ci
310f08c3bdfSopenharmony_ci	while (!finished) {
311f08c3bdfSopenharmony_ci		pid = wait(&wait_stat);
312f08c3bdfSopenharmony_ci		if (pid != -1) {
313f08c3bdfSopenharmony_ci			if (!WIFEXITED(wait_stat)
314f08c3bdfSopenharmony_ci			    || WEXITSTATUS(wait_stat) != 0)
315f08c3bdfSopenharmony_ci				tst_brk(TBROK, "child exit with err <x%x>",
316f08c3bdfSopenharmony_ci					wait_stat);
317f08c3bdfSopenharmony_ci			for (i = 0; i < nprocs; i++)
318f08c3bdfSopenharmony_ci				if (pid == pidarray[i])
319f08c3bdfSopenharmony_ci					break;
320f08c3bdfSopenharmony_ci			if (i == nprocs)
321f08c3bdfSopenharmony_ci				tst_brk(TBROK, "unknown child pid %d, <x%x>",
322f08c3bdfSopenharmony_ci					pid, wait_stat);
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci			pid = SAFE_FORK();
325f08c3bdfSopenharmony_ci			if (pid == 0) {
326f08c3bdfSopenharmony_ci				child_mapper(TEST_FILE, (unsigned int)i, (unsigned int)nprocs);
327f08c3bdfSopenharmony_ci				exit(0);
328f08c3bdfSopenharmony_ci			} else {
329f08c3bdfSopenharmony_ci				pidarray[i] = pid;
330f08c3bdfSopenharmony_ci			}
331f08c3bdfSopenharmony_ci		} else {
332f08c3bdfSopenharmony_ci			if (errno != EINTR || !finished)
333f08c3bdfSopenharmony_ci				tst_brk(TBROK | TERRNO,
334f08c3bdfSopenharmony_ci					"unexpected wait error");
335f08c3bdfSopenharmony_ci		}
336f08c3bdfSopenharmony_ci	}
337f08c3bdfSopenharmony_ci	alarm(0);
338f08c3bdfSopenharmony_ci
339f08c3bdfSopenharmony_ci	fileokay(TEST_FILE, buf);
340f08c3bdfSopenharmony_ci	tst_res(TPASS, "file has expected data");
341f08c3bdfSopenharmony_ci}
342f08c3bdfSopenharmony_ci
343f08c3bdfSopenharmony_cistatic struct tst_test test = {
344f08c3bdfSopenharmony_ci	.test_all = run,
345f08c3bdfSopenharmony_ci	.setup = setup,
346f08c3bdfSopenharmony_ci	.options = (struct tst_option[]) {
347f08c3bdfSopenharmony_ci		{"d", &debug, "Enable debug output"},
348f08c3bdfSopenharmony_ci		{"f:", &opt_filesize, "Initial filesize (default 4096)"},
349f08c3bdfSopenharmony_ci		{"m", &do_sync, "Do random msync/fsyncs as well"},
350f08c3bdfSopenharmony_ci		{"o", &do_offset, "Randomize the offset of file to map"},
351f08c3bdfSopenharmony_ci		{"p:", &opt_nprocs,
352f08c3bdfSopenharmony_ci		 "Number of mapping children to create (default 1 < ncpus < 20)"},
353f08c3bdfSopenharmony_ci		{"P:", &opt_pattern,
354f08c3bdfSopenharmony_ci		 "Use a fixed pattern (default random)"},
355f08c3bdfSopenharmony_ci		{"r", &randloops,
356f08c3bdfSopenharmony_ci		 "Randomize number of pages map children check (random % 500), "
357f08c3bdfSopenharmony_ci		 "otherwise each child checks 500 pages"},
358f08c3bdfSopenharmony_ci		{"S:", &opt_sparseoffset,
359f08c3bdfSopenharmony_ci		 "When non-zero, causes the sparse area to be left before the data, "
360f08c3bdfSopenharmony_ci		 "so that the actual initial filesize is sparseoffset + filesize "
361f08c3bdfSopenharmony_ci		 "(default 0)"},
362f08c3bdfSopenharmony_ci		{},
363f08c3bdfSopenharmony_ci	},
364f08c3bdfSopenharmony_ci	.cleanup = cleanup,
365f08c3bdfSopenharmony_ci	.max_runtime = 12,
366f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
367f08c3bdfSopenharmony_ci	.forks_child = 1,
368f08c3bdfSopenharmony_ci};
369