1f08c3bdfSopenharmony_ci/* IBM Corporation */
2f08c3bdfSopenharmony_ci/* 01/02/2003	Port to LTP avenkat@us.ibm.com */
3f08c3bdfSopenharmony_ci/* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
4f08c3bdfSopenharmony_ci/*
5f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
6f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
7f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
8f08c3bdfSopenharmony_ci *   (at your option) any later version.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
16f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
17f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#define _GNU_SOURCE 1
21f08c3bdfSopenharmony_ci#include <stdio.h>
22f08c3bdfSopenharmony_ci#include <fcntl.h>
23f08c3bdfSopenharmony_ci#include <signal.h>
24f08c3bdfSopenharmony_ci#include <sys/mman.h>
25f08c3bdfSopenharmony_ci#include <sys/wait.h>
26f08c3bdfSopenharmony_ci#include <sys/stat.h>
27f08c3bdfSopenharmony_ci#include <unistd.h>
28f08c3bdfSopenharmony_ci#include <stdlib.h>
29f08c3bdfSopenharmony_ci#include <errno.h>
30f08c3bdfSopenharmony_ci#include <sys/types.h>
31f08c3bdfSopenharmony_ci#include <limits.h>
32f08c3bdfSopenharmony_ci/*****  LTP Port        *****/
33f08c3bdfSopenharmony_ci#include "test.h"
34f08c3bdfSopenharmony_ci#define FAILED 0
35f08c3bdfSopenharmony_ci#define PASSED 1
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_ciint local_flag = PASSED;
38f08c3bdfSopenharmony_cichar *TCID = "mmapstress10";
39f08c3bdfSopenharmony_ciFILE *temp;
40f08c3bdfSopenharmony_ciint TST_TOTAL = 1;
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ciint anyfail();
43f08c3bdfSopenharmony_civoid ok_exit();
44f08c3bdfSopenharmony_ci/*****  **      **      *****/
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci/*
47f08c3bdfSopenharmony_ci *  This test stresses mmaps, specifically the code dealing with
48f08c3bdfSopenharmony_ci *  mapping of fragments.  It forks a specified number of children,
49f08c3bdfSopenharmony_ci *  all of whom mmap the same file, make a given number of accesses
50f08c3bdfSopenharmony_ci *  to random pages in the map (reading & writing and comparing data).
51f08c3bdfSopenharmony_ci *  Then the child exits and the parent forks another to take its place.
52f08c3bdfSopenharmony_ci *  Each time a child is forked, it stats the file and maps the full
53f08c3bdfSopenharmony_ci *  length of the file.  Meanwhile, another child is forked which
54f08c3bdfSopenharmony_ci *  continually writes to the file.  It loops writing some bytes (default
55f08c3bdfSopenharmony_ci *  20), then sleeps some seconds (default 1).  This causes the file
56f08c3bdfSopenharmony_ci *  to gradually grow, crossing fragment boundaries, etc.
57f08c3bdfSopenharmony_ci *  Then it forks yet *another* child who maps the file in extend
58f08c3bdfSopenharmony_ci *  mode, just to check out interaction.  (Because this will cause
59f08c3bdfSopenharmony_ci *  0 padding at end of file, children can't test as exactly as in tmmap -
60f08c3bdfSopenharmony_ci *  have to check for zero or pattern...)
61f08c3bdfSopenharmony_ci *
62f08c3bdfSopenharmony_ci *  This program continues to run until it either receives a SIGINT,
63f08c3bdfSopenharmony_ci *  or times out (if a timeout value is specified).  When either of
64f08c3bdfSopenharmony_ci *  these things happens, it cleans up its kids, then checks the
65f08c3bdfSopenharmony_ci *  file to make sure it has the correct data.
66f08c3bdfSopenharmony_ci *
67f08c3bdfSopenharmony_ci *  usage:
68f08c3bdfSopenharmony_ci *	mmapstress10 -p nprocs [-t minutes -w nbytes -s secs -f filesize
69f08c3bdfSopenharmony_ci *			 -S sparseoffset -r -o -m -l -d]
70f08c3bdfSopenharmony_ci *  where:
71f08c3bdfSopenharmony_ci *	-p nprocs	- specifies the number of mapping children
72f08c3bdfSopenharmony_ci *			  to create.  (nprocs + 1 children actually
73f08c3bdfSopenharmony_ci *			  get created, since one is the writer child)
74f08c3bdfSopenharmony_ci *	-t minutes	- specifies minutes to run.  If not specified,
75f08c3bdfSopenharmony_ci *			  default is to run forever until a SIGINT
76f08c3bdfSopenharmony_ci *			  is received.
77f08c3bdfSopenharmony_ci *	-w nbytes	- specifies number of bytes for writer process
78f08c3bdfSopenharmony_ci *			  to write at a time (i.e. between sleeps).
79f08c3bdfSopenharmony_ci *			  defaults to GROWSIZE bytes.
80f08c3bdfSopenharmony_ci *	-s secs		- specifies number of seconds for writer process
81f08c3bdfSopenharmony_ci *			  to sleep between writes.  Defaults to
82f08c3bdfSopenharmony_ci *			  SLEEPTIME seconds.
83f08c3bdfSopenharmony_ci *	-f filesize	- initial filesize (defaults to FILESIZE)
84f08c3bdfSopenharmony_ci *	-S sparseoffset - when non-zero, causes a sparse area to
85f08c3bdfSopenharmony_ci *			  be left before the data, meaning that the
86f08c3bdfSopenharmony_ci *			  actual initial file size is sparseoffset +
87f08c3bdfSopenharmony_ci *			  filesize.  Useful for testing large files.
88f08c3bdfSopenharmony_ci *			  (default is 0).
89f08c3bdfSopenharmony_ci *	-r		- randomize number of pages map children check.
90f08c3bdfSopenharmony_ci *			  (random % MAXLOOPS).  If not specified, each
91f08c3bdfSopenharmony_ci *			  child checks MAXLOOPS pages.
92f08c3bdfSopenharmony_ci *	-o		- randomize offset of file to map. (default is 0)
93f08c3bdfSopenharmony_ci *	-m		- do random msync/fsyncs as well
94f08c3bdfSopenharmony_ci *	-l		- if set, the output file is not removed on
95f08c3bdfSopenharmony_ci *			  program exit.
96f08c3bdfSopenharmony_ci *	-d		- enable debug outputd
97f08c3bdfSopenharmony_ci *
98f08c3bdfSopenharmony_ci *  Compile with -DLARGE_FILE to enable file sizes > 2 GB.
99f08c3bdfSopenharmony_ci */
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci#define MAXLOOPS	500	/* max pages for map children to write */
102f08c3bdfSopenharmony_ci#define GROWSIZE	20	/* # bytes to write per write call */
103f08c3bdfSopenharmony_ci#define SLEEPTIME	1	/* # secs to sleep between writes */
104f08c3bdfSopenharmony_ci#define	FILESIZE	4096	/* initial filesize set up by parent */
105f08c3bdfSopenharmony_ci#ifdef roundup
106f08c3bdfSopenharmony_ci#undef roundup
107f08c3bdfSopenharmony_ci#endif
108f08c3bdfSopenharmony_ci#define roundup(x, y)	((((x)+((y)-1))/(y))*(y))
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci#define SIZE_MAX UINT_MAX
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ciextern time_t time(time_t *);
113f08c3bdfSopenharmony_ciextern char *ctime(const time_t *);
114f08c3bdfSopenharmony_ciextern void *malloc(size_t);
115f08c3bdfSopenharmony_ciextern void exit(int);
116f08c3bdfSopenharmony_ciextern long lrand48(void);
117f08c3bdfSopenharmony_ciextern void srand(unsigned);
118f08c3bdfSopenharmony_ciextern void srand48(long);
119f08c3bdfSopenharmony_ciextern int rand(void);
120f08c3bdfSopenharmony_ciextern int atoi(const char *);
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_cichar *usage =
123f08c3bdfSopenharmony_ci    "-p nprocs [-t minutes -w nbytes -s secs -f fsize -S sparseoffset -r -o -m -l -d]";
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_citypedef unsigned char uchar_t;	//Ananda 12/17/02
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_civoid child_mapper(char *file, unsigned procno, unsigned nprocs);
128f08c3bdfSopenharmony_civoid child_writer(char *file, uchar_t * buf);
129f08c3bdfSopenharmony_ciint fileokay(char *file, uchar_t * expbuf);
130f08c3bdfSopenharmony_ciunsigned int initrand(void);
131f08c3bdfSopenharmony_civoid finish(int sig);
132f08c3bdfSopenharmony_civoid clean_up_file(int sig);
133f08c3bdfSopenharmony_ciint finished = 0;
134f08c3bdfSopenharmony_ciint leavefile = 0;
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ciint debug = 0;
137f08c3bdfSopenharmony_ciint growsize = GROWSIZE;
138f08c3bdfSopenharmony_ciint sleeptime = SLEEPTIME;
139f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
140f08c3bdfSopenharmony_cioff64_t filesize = FILESIZE;
141f08c3bdfSopenharmony_cioff64_t sparseoffset = 0;
142f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
143f08c3bdfSopenharmony_cioff_t filesize = FILESIZE;
144f08c3bdfSopenharmony_cioff_t sparseoffset = 0;
145f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
146f08c3bdfSopenharmony_ciunsigned randloops = 0;
147f08c3bdfSopenharmony_ciunsigned dosync = 0;
148f08c3bdfSopenharmony_ciunsigned do_offset = 0;
149f08c3bdfSopenharmony_ciunsigned pattern = 0;
150f08c3bdfSopenharmony_cistatic const char *filename = "mmapstress10.out";
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_civoid clean_mapper(int sig);
153f08c3bdfSopenharmony_civoid clean_writer(int sig);
154f08c3bdfSopenharmony_ci
155f08c3bdfSopenharmony_ciint fd_mapper = 0;
156f08c3bdfSopenharmony_cicaddr_t maddr_mapper;
157f08c3bdfSopenharmony_cisize_t mapsize_mapper;
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ciint fd_writer = 0;
160f08c3bdfSopenharmony_ci
161f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
162f08c3bdfSopenharmony_ci{
163f08c3bdfSopenharmony_ci	char *progname;
164f08c3bdfSopenharmony_ci	int fd;
165f08c3bdfSopenharmony_ci	int c;
166f08c3bdfSopenharmony_ci	extern char *optarg;
167f08c3bdfSopenharmony_ci	unsigned nprocs = 0;
168f08c3bdfSopenharmony_ci	unsigned procno;
169f08c3bdfSopenharmony_ci	pid_t *pidarray = NULL;
170f08c3bdfSopenharmony_ci	pid_t pid;
171f08c3bdfSopenharmony_ci	pid_t wr_pid = 0;
172f08c3bdfSopenharmony_ci	uchar_t *buf = NULL;
173f08c3bdfSopenharmony_ci	unsigned int seed;
174f08c3bdfSopenharmony_ci	int pagesize = sysconf(_SC_PAGE_SIZE);
175f08c3bdfSopenharmony_ci	float alarmtime = 0;
176f08c3bdfSopenharmony_ci	struct sigaction sa;
177f08c3bdfSopenharmony_ci	unsigned i;
178f08c3bdfSopenharmony_ci	int write_cnt;
179f08c3bdfSopenharmony_ci	uchar_t data;
180f08c3bdfSopenharmony_ci	int no_prob = 0;
181f08c3bdfSopenharmony_ci	int wait_stat;
182f08c3bdfSopenharmony_ci	time_t t;
183f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
184f08c3bdfSopenharmony_ci	off64_t bytes_left;
185f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
186f08c3bdfSopenharmony_ci	off_t bytes_left;
187f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
188f08c3bdfSopenharmony_ci
189f08c3bdfSopenharmony_ci	progname = *argv;
190f08c3bdfSopenharmony_ci	tst_tmpdir();
191f08c3bdfSopenharmony_ci	if (argc < 2) {
192f08c3bdfSopenharmony_ci		(void)fprintf(stderr, "usage: %s %s\n", progname, usage);
193f08c3bdfSopenharmony_ci		exit(1);
194f08c3bdfSopenharmony_ci	}
195f08c3bdfSopenharmony_ci
196f08c3bdfSopenharmony_ci	while ((c = getopt(argc, argv, "S:omdlrf:p:t:w:s:")) != -1) {
197f08c3bdfSopenharmony_ci		switch (c) {
198f08c3bdfSopenharmony_ci		case 'd':
199f08c3bdfSopenharmony_ci			debug = 1;
200f08c3bdfSopenharmony_ci			break;
201f08c3bdfSopenharmony_ci		case 't':
202f08c3bdfSopenharmony_ci			alarmtime = atof(optarg) * 60;
203f08c3bdfSopenharmony_ci			break;
204f08c3bdfSopenharmony_ci		case 'p':
205f08c3bdfSopenharmony_ci			nprocs = atoi(optarg);
206f08c3bdfSopenharmony_ci			break;
207f08c3bdfSopenharmony_ci		case 'l':
208f08c3bdfSopenharmony_ci			leavefile = 1;
209f08c3bdfSopenharmony_ci			break;
210f08c3bdfSopenharmony_ci		case 's':
211f08c3bdfSopenharmony_ci			sleeptime = atoi(optarg);
212f08c3bdfSopenharmony_ci			if (sleeptime < 0) {
213f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "error: negative "
214f08c3bdfSopenharmony_ci					      "sleeptime\n");
215f08c3bdfSopenharmony_ci				anyfail();
216f08c3bdfSopenharmony_ci			}
217f08c3bdfSopenharmony_ci			break;
218f08c3bdfSopenharmony_ci		case 'w':
219f08c3bdfSopenharmony_ci			growsize = atoi(optarg);
220f08c3bdfSopenharmony_ci			if (growsize < 0) {
221f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "error: negative write "
222f08c3bdfSopenharmony_ci					      "size\n");
223f08c3bdfSopenharmony_ci				anyfail();
224f08c3bdfSopenharmony_ci			}
225f08c3bdfSopenharmony_ci			break;
226f08c3bdfSopenharmony_ci		case 'f':
227f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
228f08c3bdfSopenharmony_ci			filesize = atoll(optarg);
229f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
230f08c3bdfSopenharmony_ci			filesize = atoi(optarg);
231f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
232f08c3bdfSopenharmony_ci			if (filesize < 0) {
233f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "error: negative "
234f08c3bdfSopenharmony_ci					      "filesize\n");
235f08c3bdfSopenharmony_ci				anyfail();
236f08c3bdfSopenharmony_ci			}
237f08c3bdfSopenharmony_ci			break;
238f08c3bdfSopenharmony_ci		case 'r':
239f08c3bdfSopenharmony_ci			randloops = 1;
240f08c3bdfSopenharmony_ci			break;
241f08c3bdfSopenharmony_ci		case 'm':
242f08c3bdfSopenharmony_ci			dosync = 1;
243f08c3bdfSopenharmony_ci			break;
244f08c3bdfSopenharmony_ci		case 'o':
245f08c3bdfSopenharmony_ci			do_offset = 1;
246f08c3bdfSopenharmony_ci			break;
247f08c3bdfSopenharmony_ci		case 'S':
248f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
249f08c3bdfSopenharmony_ci			sparseoffset = atoll(optarg);
250f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
251f08c3bdfSopenharmony_ci			sparseoffset = atoi(optarg);
252f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
253f08c3bdfSopenharmony_ci			if (sparseoffset % pagesize != 0) {
254f08c3bdfSopenharmony_ci				fprintf(stderr,
255f08c3bdfSopenharmony_ci					"sparseoffset must be pagesize multiple\n");
256f08c3bdfSopenharmony_ci				anyfail();
257f08c3bdfSopenharmony_ci			}
258f08c3bdfSopenharmony_ci			break;
259f08c3bdfSopenharmony_ci		default:
260f08c3bdfSopenharmony_ci			(void)fprintf(stderr, "usage: %s %s\n", progname,
261f08c3bdfSopenharmony_ci				      usage);
262f08c3bdfSopenharmony_ci			anyfail();
263f08c3bdfSopenharmony_ci		}
264f08c3bdfSopenharmony_ci	}
265f08c3bdfSopenharmony_ci
266f08c3bdfSopenharmony_ci	if (nprocs > 255) {
267f08c3bdfSopenharmony_ci		(void)fprintf(stderr, "invalid nprocs %d - (range 0-255)\n",
268f08c3bdfSopenharmony_ci			      nprocs);
269f08c3bdfSopenharmony_ci		anyfail();
270f08c3bdfSopenharmony_ci	}
271f08c3bdfSopenharmony_ci	(void)time(&t);
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_ci	seed = initrand();
274f08c3bdfSopenharmony_ci	pattern = seed & 0xff;
275f08c3bdfSopenharmony_ci
276f08c3bdfSopenharmony_ci	if (debug) {
277f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
278f08c3bdfSopenharmony_ci		(void)printf("creating file <%s> with %Ld bytes, pattern %d\n",
279f08c3bdfSopenharmony_ci			     filename, filesize, pattern);
280f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
281f08c3bdfSopenharmony_ci		(void)printf("creating file <%s> with %ld bytes, pattern %d\n",
282f08c3bdfSopenharmony_ci			     filename, filesize, pattern);
283f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
284f08c3bdfSopenharmony_ci		if (alarmtime)
285f08c3bdfSopenharmony_ci			(void)printf("running for %f minutes\n",
286f08c3bdfSopenharmony_ci				     alarmtime / 60);
287f08c3bdfSopenharmony_ci		else
288f08c3bdfSopenharmony_ci			(void)printf("running with no time limit\n");
289f08c3bdfSopenharmony_ci	}
290f08c3bdfSopenharmony_ci
291f08c3bdfSopenharmony_ci	/*
292f08c3bdfSopenharmony_ci	 *  Plan for death by signal.  User may have specified
293f08c3bdfSopenharmony_ci	 *  a time limit, in which case set an alarm and catch SIGALRM.
294f08c3bdfSopenharmony_ci	 *  Also catch and cleanup with SIGINT, SIGQUIT, and SIGTERM.
295f08c3bdfSopenharmony_ci	 */
296f08c3bdfSopenharmony_ci	sa.sa_handler = finish;
297f08c3bdfSopenharmony_ci	sa.sa_flags = 0;
298f08c3bdfSopenharmony_ci	if (sigemptyset(&sa.sa_mask)) {
299f08c3bdfSopenharmony_ci		perror("sigempty error");
300f08c3bdfSopenharmony_ci		goto cleanup;
301f08c3bdfSopenharmony_ci	}
302f08c3bdfSopenharmony_ci
303f08c3bdfSopenharmony_ci	if (sigaction(SIGINT, &sa, 0) == -1) {
304f08c3bdfSopenharmony_ci		perror("sigaction error SIGINT");
305f08c3bdfSopenharmony_ci		goto cleanup;
306f08c3bdfSopenharmony_ci	}
307f08c3bdfSopenharmony_ci	if (alarmtime) {
308f08c3bdfSopenharmony_ci		if (sigaction(SIGALRM, &sa, 0) == -1) {
309f08c3bdfSopenharmony_ci			perror("sigaction error");
310f08c3bdfSopenharmony_ci			goto cleanup;
311f08c3bdfSopenharmony_ci		}
312f08c3bdfSopenharmony_ci		(void)alarm(alarmtime);
313f08c3bdfSopenharmony_ci	}
314f08c3bdfSopenharmony_ci	/* If we get a SIGQUIT or SIGTERM, clean up and exit immediately. */
315f08c3bdfSopenharmony_ci	sa.sa_handler = clean_up_file;
316f08c3bdfSopenharmony_ci	if (sigaction(SIGQUIT, &sa, 0) == -1) {
317f08c3bdfSopenharmony_ci		perror("sigaction error SIGQUIT");
318f08c3bdfSopenharmony_ci		goto cleanup;
319f08c3bdfSopenharmony_ci	}
320f08c3bdfSopenharmony_ci	if (sigaction(SIGTERM, &sa, 0) == -1) {
321f08c3bdfSopenharmony_ci		perror("sigaction error SIGTERM");
322f08c3bdfSopenharmony_ci		goto cleanup;
323f08c3bdfSopenharmony_ci	}
324f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
325f08c3bdfSopenharmony_ci	if ((fd = open64(filename, O_CREAT | O_TRUNC | O_RDWR, 0664)) == -1) {
326f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
327f08c3bdfSopenharmony_ci	if ((fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0664)) == -1) {
328f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
329f08c3bdfSopenharmony_ci		perror("open error");
330f08c3bdfSopenharmony_ci		anyfail();
331f08c3bdfSopenharmony_ci	}
332f08c3bdfSopenharmony_ci
333f08c3bdfSopenharmony_ci	if ((buf = malloc(pagesize + growsize)) == NULL
334f08c3bdfSopenharmony_ci	    || (pidarray = malloc(nprocs * sizeof(pid_t))) == NULL) {
335f08c3bdfSopenharmony_ci		perror("malloc error");
336f08c3bdfSopenharmony_ci		anyfail();
337f08c3bdfSopenharmony_ci	}
338f08c3bdfSopenharmony_ci
339f08c3bdfSopenharmony_ci	for (i = 0; i < nprocs; i++)
340f08c3bdfSopenharmony_ci		*(pidarray + i) = 0;
341f08c3bdfSopenharmony_ci
342f08c3bdfSopenharmony_ci	for (i = 0, data = 0; i < pagesize; i++) {
343f08c3bdfSopenharmony_ci		*(buf + i) = (data + pattern) & 0xff;
344f08c3bdfSopenharmony_ci		if (++data == nprocs)
345f08c3bdfSopenharmony_ci			data = 0;
346f08c3bdfSopenharmony_ci	}
347f08c3bdfSopenharmony_ci	for (data = 0; i < pagesize + growsize; i++) {
348f08c3bdfSopenharmony_ci		*(buf + i) = (data + pattern) & 0xff;
349f08c3bdfSopenharmony_ci		if (++data == nprocs)
350f08c3bdfSopenharmony_ci			data = 0;
351f08c3bdfSopenharmony_ci	}
352f08c3bdfSopenharmony_ci
353f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
354f08c3bdfSopenharmony_ci	if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
355f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
356f08c3bdfSopenharmony_ci	if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
357f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
358f08c3bdfSopenharmony_ci		perror("lseek");
359f08c3bdfSopenharmony_ci		anyfail();
360f08c3bdfSopenharmony_ci	}
361f08c3bdfSopenharmony_ci
362f08c3bdfSopenharmony_ci	for (bytes_left = filesize; bytes_left; bytes_left -= c) {
363f08c3bdfSopenharmony_ci		write_cnt = MIN(pagesize, (int)bytes_left);
364f08c3bdfSopenharmony_ci		if ((c = write(fd, (char *)buf, write_cnt)) != write_cnt) {
365f08c3bdfSopenharmony_ci			if (c == -1) {
366f08c3bdfSopenharmony_ci				perror("write error");
367f08c3bdfSopenharmony_ci			} else {
368f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "write: wrote %d of %d "
369f08c3bdfSopenharmony_ci					      "bytes\n", c, write_cnt);
370f08c3bdfSopenharmony_ci			}
371f08c3bdfSopenharmony_ci			(void)close(fd);
372f08c3bdfSopenharmony_ci			(void)unlink(filename);
373f08c3bdfSopenharmony_ci			anyfail();
374f08c3bdfSopenharmony_ci		}
375f08c3bdfSopenharmony_ci	}
376f08c3bdfSopenharmony_ci
377f08c3bdfSopenharmony_ci	(void)close(fd);
378f08c3bdfSopenharmony_ci
379f08c3bdfSopenharmony_ci	/*
380f08c3bdfSopenharmony_ci	 *  Fork off mmap children.
381f08c3bdfSopenharmony_ci	 */
382f08c3bdfSopenharmony_ci	for (procno = 0; procno < nprocs; procno++) {
383f08c3bdfSopenharmony_ci		switch (pid = fork()) {
384f08c3bdfSopenharmony_ci
385f08c3bdfSopenharmony_ci		case -1:
386f08c3bdfSopenharmony_ci			perror("fork error");
387f08c3bdfSopenharmony_ci			goto cleanup;
388f08c3bdfSopenharmony_ci
389f08c3bdfSopenharmony_ci		case 0:
390f08c3bdfSopenharmony_ci			child_mapper(filename, procno, nprocs);
391f08c3bdfSopenharmony_ci			exit(0);
392f08c3bdfSopenharmony_ci
393f08c3bdfSopenharmony_ci		default:
394f08c3bdfSopenharmony_ci			pidarray[procno] = pid;
395f08c3bdfSopenharmony_ci		}
396f08c3bdfSopenharmony_ci	}
397f08c3bdfSopenharmony_ci
398f08c3bdfSopenharmony_ci	/*
399f08c3bdfSopenharmony_ci	 *  Now fork off an additional process to continually
400f08c3bdfSopenharmony_ci	 *  write to (and grow) the file.
401f08c3bdfSopenharmony_ci	 */
402f08c3bdfSopenharmony_ci	if ((wr_pid = fork()) == -1) {
403f08c3bdfSopenharmony_ci		perror("fork error");
404f08c3bdfSopenharmony_ci		goto cleanup;
405f08c3bdfSopenharmony_ci	} else if (wr_pid == 0) {	/* child */
406f08c3bdfSopenharmony_ci		child_writer(filename, buf);
407f08c3bdfSopenharmony_ci		exit(0);
408f08c3bdfSopenharmony_ci	}
409f08c3bdfSopenharmony_ci
410f08c3bdfSopenharmony_ci	/*
411f08c3bdfSopenharmony_ci	 *  Now wait for children and refork them as needed.
412f08c3bdfSopenharmony_ci	 */
413f08c3bdfSopenharmony_ci
414f08c3bdfSopenharmony_ci	while (!finished) {
415f08c3bdfSopenharmony_ci		pid = wait(&wait_stat);
416f08c3bdfSopenharmony_ci		/*
417f08c3bdfSopenharmony_ci		 *  Block signals while processing child exit.
418f08c3bdfSopenharmony_ci		 */
419f08c3bdfSopenharmony_ci
420f08c3bdfSopenharmony_ci		if (sighold(SIGALRM) || sighold(SIGINT)) {
421f08c3bdfSopenharmony_ci			perror("sighold error");
422f08c3bdfSopenharmony_ci			goto cleanup;
423f08c3bdfSopenharmony_ci		}
424f08c3bdfSopenharmony_ci
425f08c3bdfSopenharmony_ci		if (pid != -1) {
426f08c3bdfSopenharmony_ci			/*
427f08c3bdfSopenharmony_ci			 *  Check exit status, then refork with the
428f08c3bdfSopenharmony_ci			 *  appropriate procno.
429f08c3bdfSopenharmony_ci			 */
430f08c3bdfSopenharmony_ci			if (!WIFEXITED(wait_stat)
431f08c3bdfSopenharmony_ci			    || WEXITSTATUS(wait_stat) != 0) {
432f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "child exit with err "
433f08c3bdfSopenharmony_ci					      "<x%x>\n", wait_stat);
434f08c3bdfSopenharmony_ci				goto cleanup;
435f08c3bdfSopenharmony_ci			}
436f08c3bdfSopenharmony_ci			for (i = 0; i < nprocs; i++)
437f08c3bdfSopenharmony_ci				if (pid == pidarray[i])
438f08c3bdfSopenharmony_ci					break;
439f08c3bdfSopenharmony_ci			if (i == nprocs) {
440f08c3bdfSopenharmony_ci				if (pid == wr_pid) {
441f08c3bdfSopenharmony_ci					(void)fprintf(stderr,
442f08c3bdfSopenharmony_ci						      "writer child unexpected exit <x%x>\n",
443f08c3bdfSopenharmony_ci						      wait_stat);
444f08c3bdfSopenharmony_ci					wr_pid = 0;
445f08c3bdfSopenharmony_ci				} else
446f08c3bdfSopenharmony_ci					(void)fprintf(stderr, "unknown child "
447f08c3bdfSopenharmony_ci						      "pid %d, <x%x>\n",
448f08c3bdfSopenharmony_ci						      pid, wait_stat);
449f08c3bdfSopenharmony_ci				goto cleanup;
450f08c3bdfSopenharmony_ci			}
451f08c3bdfSopenharmony_ci
452f08c3bdfSopenharmony_ci			if ((pid = fork()) == -1) {
453f08c3bdfSopenharmony_ci				perror("fork error");
454f08c3bdfSopenharmony_ci				pidarray[i] = 0;
455f08c3bdfSopenharmony_ci				goto cleanup;
456f08c3bdfSopenharmony_ci			} else if (pid == 0) {	/* child */
457f08c3bdfSopenharmony_ci				child_mapper(filename, i, nprocs);
458f08c3bdfSopenharmony_ci				exit(0);
459f08c3bdfSopenharmony_ci			} else
460f08c3bdfSopenharmony_ci				pidarray[i] = pid;
461f08c3bdfSopenharmony_ci		} else {
462f08c3bdfSopenharmony_ci			/*
463f08c3bdfSopenharmony_ci			 *  wait returned an error.  If EINTR, then
464f08c3bdfSopenharmony_ci			 *  normal finish, else it's an unexpected
465f08c3bdfSopenharmony_ci			 *  error...
466f08c3bdfSopenharmony_ci			 */
467f08c3bdfSopenharmony_ci			if (errno != EINTR || !finished) {
468f08c3bdfSopenharmony_ci				perror("unexpected wait error");
469f08c3bdfSopenharmony_ci				goto cleanup;
470f08c3bdfSopenharmony_ci			}
471f08c3bdfSopenharmony_ci		}
472f08c3bdfSopenharmony_ci		if (sigrelse(SIGALRM) || sigrelse(SIGINT)) {
473f08c3bdfSopenharmony_ci			perror("sigrelse error");
474f08c3bdfSopenharmony_ci			goto cleanup;
475f08c3bdfSopenharmony_ci		}
476f08c3bdfSopenharmony_ci	}
477f08c3bdfSopenharmony_ci
478f08c3bdfSopenharmony_ci	/*
479f08c3bdfSopenharmony_ci	 *  Finished!  Check the file for sanity, then kill all
480f08c3bdfSopenharmony_ci	 *  the children and done!.
481f08c3bdfSopenharmony_ci	 */
482f08c3bdfSopenharmony_ci
483f08c3bdfSopenharmony_ci	(void)alarm(0);
484f08c3bdfSopenharmony_ci	no_prob = 1;
485f08c3bdfSopenharmony_ci
486f08c3bdfSopenharmony_cicleanup:
487f08c3bdfSopenharmony_ci	for (i = 0; i < nprocs; i++)
488f08c3bdfSopenharmony_ci		(void)kill(pidarray[i], SIGUSR1);
489f08c3bdfSopenharmony_ci	(void)kill(wr_pid, SIGUSR1);
490f08c3bdfSopenharmony_ci
491f08c3bdfSopenharmony_ci	while (wait(&wait_stat) != -1 || errno != ECHILD)
492f08c3bdfSopenharmony_ci		continue;
493f08c3bdfSopenharmony_ci
494f08c3bdfSopenharmony_ci	if (no_prob) {		/* only check file if no errors */
495f08c3bdfSopenharmony_ci		if (!fileokay(filename, buf)) {
496f08c3bdfSopenharmony_ci			(void)fprintf(stderr, "file data incorrect!\n");
497f08c3bdfSopenharmony_ci			(void)printf("  leaving file <%s>\n", filename);
498f08c3bdfSopenharmony_ci			anyfail();
499f08c3bdfSopenharmony_ci
500f08c3bdfSopenharmony_ci		} else {
501f08c3bdfSopenharmony_ci			(void)printf("file data okay\n");
502f08c3bdfSopenharmony_ci			if (!leavefile)
503f08c3bdfSopenharmony_ci				(void)unlink(filename);
504f08c3bdfSopenharmony_ci		}
505f08c3bdfSopenharmony_ci	} else
506f08c3bdfSopenharmony_ci		(void)printf("  leaving file <%s>\n", filename);
507f08c3bdfSopenharmony_ci
508f08c3bdfSopenharmony_ci	(void)time(&t);
509f08c3bdfSopenharmony_ci//      (void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port
510f08c3bdfSopenharmony_ci	ok_exit();
511f08c3bdfSopenharmony_ci	tst_exit();
512f08c3bdfSopenharmony_ci}
513f08c3bdfSopenharmony_ci
514f08c3bdfSopenharmony_ci/*
515f08c3bdfSopenharmony_ci *  Child process that reads/writes map.  The child stats the file
516f08c3bdfSopenharmony_ci *  to determine the size, maps the size of the file, then reads/writes
517f08c3bdfSopenharmony_ci *  its own locations on random pages of the map (its locations being
518f08c3bdfSopenharmony_ci *  determined based on nprocs & procno).  After a specific number of
519f08c3bdfSopenharmony_ci *  iterations, it exits.
520f08c3bdfSopenharmony_ci */
521f08c3bdfSopenharmony_civoid child_mapper(char *file, unsigned procno, unsigned nprocs)
522f08c3bdfSopenharmony_ci{
523f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
524f08c3bdfSopenharmony_ci	struct stat64 statbuf;
525f08c3bdfSopenharmony_ci	off64_t filesize;
526f08c3bdfSopenharmony_ci	off64_t offset;
527f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
528f08c3bdfSopenharmony_ci	struct stat statbuf;
529f08c3bdfSopenharmony_ci	off_t filesize;
530f08c3bdfSopenharmony_ci	off_t offset;
531f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
532f08c3bdfSopenharmony_ci	size_t validsize;
533f08c3bdfSopenharmony_ci	caddr_t paddr;
534f08c3bdfSopenharmony_ci	int pagesize = sysconf(_SC_PAGE_SIZE);
535f08c3bdfSopenharmony_ci	unsigned randpage;
536f08c3bdfSopenharmony_ci	unsigned int seed;
537f08c3bdfSopenharmony_ci	unsigned loopcnt;
538f08c3bdfSopenharmony_ci	unsigned nloops;
539f08c3bdfSopenharmony_ci	unsigned mappages;
540f08c3bdfSopenharmony_ci	unsigned mapflags;
541f08c3bdfSopenharmony_ci	unsigned i;
542f08c3bdfSopenharmony_ci	struct sigaction sa_mapper;
543f08c3bdfSopenharmony_ci
544f08c3bdfSopenharmony_ci	mapflags = MAP_SHARED;
545f08c3bdfSopenharmony_ci
546f08c3bdfSopenharmony_ci	seed = initrand();	/* initialize random seed */
547f08c3bdfSopenharmony_ci
548f08c3bdfSopenharmony_ci	sa_mapper.sa_handler = clean_mapper;
549f08c3bdfSopenharmony_ci	sa_mapper.sa_flags = 0;
550f08c3bdfSopenharmony_ci	if (sigemptyset(&sa_mapper.sa_mask)) {
551f08c3bdfSopenharmony_ci		perror("sigempty error");
552f08c3bdfSopenharmony_ci		anyfail();
553f08c3bdfSopenharmony_ci	}
554f08c3bdfSopenharmony_ci
555f08c3bdfSopenharmony_ci	if (sigaction(SIGUSR1, &sa_mapper, 0) == -1) {
556f08c3bdfSopenharmony_ci		perror("sigaction error SIGUSR1");
557f08c3bdfSopenharmony_ci		anyfail();
558f08c3bdfSopenharmony_ci	}
559f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
560f08c3bdfSopenharmony_ci	if ((fd_mapper = open64(file, O_RDWR)) == -1) {
561f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
562f08c3bdfSopenharmony_ci	if ((fd_mapper = open(file, O_RDWR)) == -1) {
563f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
564f08c3bdfSopenharmony_ci		perror("open error");
565f08c3bdfSopenharmony_ci		anyfail();
566f08c3bdfSopenharmony_ci	}
567f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
568f08c3bdfSopenharmony_ci	if (fstat64(fd_mapper, &statbuf) == -1) {
569f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
570f08c3bdfSopenharmony_ci	if (fstat(fd_mapper, &statbuf) == -1) {
571f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
572f08c3bdfSopenharmony_ci		perror("stat error");
573f08c3bdfSopenharmony_ci		anyfail();
574f08c3bdfSopenharmony_ci	}
575f08c3bdfSopenharmony_ci	filesize = statbuf.st_size;
576f08c3bdfSopenharmony_ci
577f08c3bdfSopenharmony_ci	if (statbuf.st_size - sparseoffset > SIZE_MAX) {
578f08c3bdfSopenharmony_ci		fprintf(stderr, "size_t overflow when setting up map\n");
579f08c3bdfSopenharmony_ci		anyfail();
580f08c3bdfSopenharmony_ci	}
581f08c3bdfSopenharmony_ci	mapsize_mapper = (size_t) (statbuf.st_size - sparseoffset);
582f08c3bdfSopenharmony_ci	mappages = roundup(mapsize_mapper, pagesize) / pagesize;
583f08c3bdfSopenharmony_ci	offset = sparseoffset;
584f08c3bdfSopenharmony_ci	if (do_offset) {
585f08c3bdfSopenharmony_ci		int pageoffset = lrand48() % mappages;
586f08c3bdfSopenharmony_ci		int byteoffset = pageoffset * pagesize;
587f08c3bdfSopenharmony_ci		offset += byteoffset;
588f08c3bdfSopenharmony_ci		mapsize_mapper -= byteoffset;
589f08c3bdfSopenharmony_ci		mappages -= pageoffset;
590f08c3bdfSopenharmony_ci	}
591f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
592f08c3bdfSopenharmony_ci	if ((maddr_mapper = mmap64(0, mapsize_mapper, PROT_READ | PROT_WRITE,
593f08c3bdfSopenharmony_ci				   mapflags, fd_mapper,
594f08c3bdfSopenharmony_ci				   offset)) == (caddr_t) - 1) {
595f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
596f08c3bdfSopenharmony_ci	if ((maddr_mapper = mmap(0, mapsize_mapper, PROT_READ | PROT_WRITE,
597f08c3bdfSopenharmony_ci				 mapflags, fd_mapper,
598f08c3bdfSopenharmony_ci				 offset)) == (caddr_t) - 1) {
599f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
600f08c3bdfSopenharmony_ci		perror("mmap error");
601f08c3bdfSopenharmony_ci		anyfail();
602f08c3bdfSopenharmony_ci	}
603f08c3bdfSopenharmony_ci
604f08c3bdfSopenharmony_ci	(void)close(fd_mapper);
605f08c3bdfSopenharmony_ci
606f08c3bdfSopenharmony_ci	nloops = (randloops) ? (lrand48() % MAXLOOPS) : MAXLOOPS;
607f08c3bdfSopenharmony_ci
608f08c3bdfSopenharmony_ci	if (debug) {
609f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
610f08c3bdfSopenharmony_ci		(void)printf("child %d (pid %ld): seed %d, fsize %Ld, "
611f08c3bdfSopenharmony_ci			     "mapsize %d, off %Ld, loop %d\n",
612f08c3bdfSopenharmony_ci			     procno, getpid(), seed, filesize, mapsize_mapper,
613f08c3bdfSopenharmony_ci			     offset / pagesize, nloops);
614f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
615f08c3bdfSopenharmony_ci		(void)printf("child %d (pid %d): seed %d, fsize %ld, "
616f08c3bdfSopenharmony_ci			     "mapsize %ld, off %ld, loop %d\n",
617f08c3bdfSopenharmony_ci			     procno, getpid(), seed, filesize,
618f08c3bdfSopenharmony_ci			     (long)mapsize_mapper, offset / pagesize, nloops);
619f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
620f08c3bdfSopenharmony_ci	}
621f08c3bdfSopenharmony_ci
622f08c3bdfSopenharmony_ci	/*
623f08c3bdfSopenharmony_ci	 *  Now loop read/writing random pages.
624f08c3bdfSopenharmony_ci	 */
625f08c3bdfSopenharmony_ci	for (loopcnt = 0; loopcnt < nloops; loopcnt++) {
626f08c3bdfSopenharmony_ci		randpage = lrand48() % mappages;
627f08c3bdfSopenharmony_ci		paddr = maddr_mapper + (randpage * pagesize);	/* page address */
628f08c3bdfSopenharmony_ci
629f08c3bdfSopenharmony_ci		if (randpage < mappages - 1 || !(mapsize_mapper % pagesize))
630f08c3bdfSopenharmony_ci			validsize = pagesize;
631f08c3bdfSopenharmony_ci		else
632f08c3bdfSopenharmony_ci			validsize = mapsize_mapper % pagesize;
633f08c3bdfSopenharmony_ci
634f08c3bdfSopenharmony_ci		/*
635f08c3bdfSopenharmony_ci		 * Because one child is mapping file in extend mode,
636f08c3bdfSopenharmony_ci		 * it may be padded with zeros at end.  So we can't
637f08c3bdfSopenharmony_ci		 * do an exact check -- accept known pattern OR zeros.
638f08c3bdfSopenharmony_ci		 */
639f08c3bdfSopenharmony_ci		for (i = procno; i < validsize; i += nprocs) {
640f08c3bdfSopenharmony_ci			if (*((unsigned char *)(paddr + i))
641f08c3bdfSopenharmony_ci			    != ((procno + pattern) & 0xff)
642f08c3bdfSopenharmony_ci			    && *((unsigned char *)(paddr + i)) != 0) {
643f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "child %d: invalid data "
644f08c3bdfSopenharmony_ci					      "<x%x>", procno,
645f08c3bdfSopenharmony_ci					      *((unsigned char *)(paddr + i)));
646f08c3bdfSopenharmony_ci				(void)fprintf(stderr,
647f08c3bdfSopenharmony_ci					      " at pg %d off %d, exp "
648f08c3bdfSopenharmony_ci					      "<x%x>\n", randpage, i,
649f08c3bdfSopenharmony_ci					      (procno + pattern) & 0xff);
650f08c3bdfSopenharmony_ci				anyfail();
651f08c3bdfSopenharmony_ci			}
652f08c3bdfSopenharmony_ci			/*
653f08c3bdfSopenharmony_ci			 *  Now write it.
654f08c3bdfSopenharmony_ci			 */
655f08c3bdfSopenharmony_ci
656f08c3bdfSopenharmony_ci			*(paddr + i) = (procno + pattern) & 0xff;
657f08c3bdfSopenharmony_ci		}
658f08c3bdfSopenharmony_ci	}
659f08c3bdfSopenharmony_ci	if (dosync) {
660f08c3bdfSopenharmony_ci		/*
661f08c3bdfSopenharmony_ci		 * Exercise msync() as well!
662f08c3bdfSopenharmony_ci		 */
663f08c3bdfSopenharmony_ci		randpage = lrand48() % mappages;
664f08c3bdfSopenharmony_ci		paddr = maddr_mapper + (randpage * pagesize);	/* page address */
665f08c3bdfSopenharmony_ci		if (msync(paddr, (mappages - randpage) * pagesize,
666f08c3bdfSopenharmony_ci			  MS_SYNC) == -1) {
667f08c3bdfSopenharmony_ci			perror("msync error");
668f08c3bdfSopenharmony_ci			anyfail();
669f08c3bdfSopenharmony_ci		}
670f08c3bdfSopenharmony_ci	}
671f08c3bdfSopenharmony_ci	if (munmap(maddr_mapper, mapsize_mapper) == -1) {
672f08c3bdfSopenharmony_ci		perror("munmap failed");
673f08c3bdfSopenharmony_ci		anyfail();
674f08c3bdfSopenharmony_ci	}
675f08c3bdfSopenharmony_ci	exit(0);
676f08c3bdfSopenharmony_ci}
677f08c3bdfSopenharmony_ci
678f08c3bdfSopenharmony_ci/*
679f08c3bdfSopenharmony_ci *  child_writer
680f08c3bdfSopenharmony_ci * 	The child process that continually (and slowly!!) grows
681f08c3bdfSopenharmony_ci *	the file.  The purpose of this is to exercise the code
682f08c3bdfSopenharmony_ci *	supporting mapping of fragments.  The map children are
683f08c3bdfSopenharmony_ci *	constantly reforking and will pick up the map changes, etc.
684f08c3bdfSopenharmony_ci *	This process executes until signalled (i.e. has no exit!)
685f08c3bdfSopenharmony_ci *	unless error.
686f08c3bdfSopenharmony_ci */
687f08c3bdfSopenharmony_civoid child_writer(char *file, uchar_t * buf)
688f08c3bdfSopenharmony_ci{				/* buf already set up in main */
689f08c3bdfSopenharmony_ci	struct sigaction sa_writer;
690f08c3bdfSopenharmony_ci
691f08c3bdfSopenharmony_ci	sa_writer.sa_handler = clean_writer;
692f08c3bdfSopenharmony_ci	sa_writer.sa_flags = 0;
693f08c3bdfSopenharmony_ci	if (sigemptyset(&sa_writer.sa_mask)) {
694f08c3bdfSopenharmony_ci		perror("sigempty error");
695f08c3bdfSopenharmony_ci		anyfail();
696f08c3bdfSopenharmony_ci	}
697f08c3bdfSopenharmony_ci
698f08c3bdfSopenharmony_ci	if (sigaction(SIGUSR1, &sa_writer, 0) == -1) {
699f08c3bdfSopenharmony_ci		perror("sigaction error SIGUSR1");
700f08c3bdfSopenharmony_ci		anyfail();
701f08c3bdfSopenharmony_ci	}
702f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
703f08c3bdfSopenharmony_ci	struct stat64 statbuf;
704f08c3bdfSopenharmony_ci	off64_t off;
705f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
706f08c3bdfSopenharmony_ci	struct stat statbuf;
707f08c3bdfSopenharmony_ci	off_t off;
708f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
709f08c3bdfSopenharmony_ci	int pagesize = sysconf(_SC_PAGE_SIZE);
710f08c3bdfSopenharmony_ci	uchar_t *p;
711f08c3bdfSopenharmony_ci	int cnt;
712f08c3bdfSopenharmony_ci
713f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
714f08c3bdfSopenharmony_ci	if ((fd_writer = open64(file, O_RDWR)) == -1) {
715f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
716f08c3bdfSopenharmony_ci	if ((fd_writer = open(file, O_RDWR)) == -1) {
717f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
718f08c3bdfSopenharmony_ci		perror("open error");
719f08c3bdfSopenharmony_ci		anyfail();
720f08c3bdfSopenharmony_ci	}
721f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
722f08c3bdfSopenharmony_ci	if ((off = lseek64(fd_writer, 0, SEEK_END)) == -1) {
723f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
724f08c3bdfSopenharmony_ci	if ((off = lseek(fd_writer, 0, SEEK_END)) == -1) {
725f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
726f08c3bdfSopenharmony_ci		perror("lseek error");
727f08c3bdfSopenharmony_ci		anyfail();
728f08c3bdfSopenharmony_ci	}
729f08c3bdfSopenharmony_ci
730f08c3bdfSopenharmony_ci	for (;;) {
731f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
732f08c3bdfSopenharmony_ci		if (fstat64(fd_writer, &statbuf) == -1) {
733f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
734f08c3bdfSopenharmony_ci		if (fstat(fd_writer, &statbuf) == -1) {
735f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
736f08c3bdfSopenharmony_ci			perror("fstat error");
737f08c3bdfSopenharmony_ci			anyfail();
738f08c3bdfSopenharmony_ci		}
739f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
740f08c3bdfSopenharmony_ci		if (debug)
741f08c3bdfSopenharmony_ci			(void)printf("writer %d bytes at off %Ld, size %Ld\n",
742f08c3bdfSopenharmony_ci				     growsize, off, statbuf.st_size);
743f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
744f08c3bdfSopenharmony_ci		if (debug)
745f08c3bdfSopenharmony_ci			(void)printf("writer %d bytes at off %ld, size %ld\n",
746f08c3bdfSopenharmony_ci				     growsize, off, statbuf.st_size);
747f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
748f08c3bdfSopenharmony_ci
749f08c3bdfSopenharmony_ci		/*
750f08c3bdfSopenharmony_ci		 *  Write some number of bytes, then sleep some
751f08c3bdfSopenharmony_ci		 *  number of seconds...
752f08c3bdfSopenharmony_ci		 *  Need to keep track of our offset so write the
753f08c3bdfSopenharmony_ci		 *  right bytes.
754f08c3bdfSopenharmony_ci		 */
755f08c3bdfSopenharmony_ci
756f08c3bdfSopenharmony_ci		p = buf + (off % pagesize);
757f08c3bdfSopenharmony_ci
758f08c3bdfSopenharmony_ci		if ((cnt = write(fd_writer, p, growsize)) != growsize) {
759f08c3bdfSopenharmony_ci			if (cnt == -1)
760f08c3bdfSopenharmony_ci				perror("write error");
761f08c3bdfSopenharmony_ci			else
762f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "wrote %d of %d bytes\n",
763f08c3bdfSopenharmony_ci					      cnt, growsize);
764f08c3bdfSopenharmony_ci			anyfail();
765f08c3bdfSopenharmony_ci		}
766f08c3bdfSopenharmony_ci
767f08c3bdfSopenharmony_ci		off += growsize;
768f08c3bdfSopenharmony_ci
769f08c3bdfSopenharmony_ci		(void)sleep(sleeptime);
770f08c3bdfSopenharmony_ci		if (dosync) {
771f08c3bdfSopenharmony_ci			if (fsync(fd_writer) == -1) {
772f08c3bdfSopenharmony_ci				perror("fsync error");
773f08c3bdfSopenharmony_ci				anyfail();
774f08c3bdfSopenharmony_ci			}
775f08c3bdfSopenharmony_ci		}
776f08c3bdfSopenharmony_ci	}
777f08c3bdfSopenharmony_ci	close(fd_writer);
778f08c3bdfSopenharmony_ci}
779f08c3bdfSopenharmony_ci
780f08c3bdfSopenharmony_ci/*
781f08c3bdfSopenharmony_ci *  Make sure file has all the correct data.
782f08c3bdfSopenharmony_ci
783f08c3bdfSopenharmony_ci */
784f08c3bdfSopenharmony_ciint fileokay(char *file, uchar_t * expbuf)
785f08c3bdfSopenharmony_ci{
786f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
787f08c3bdfSopenharmony_ci	struct stat64 statbuf;
788f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
789f08c3bdfSopenharmony_ci	struct stat statbuf;
790f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
791f08c3bdfSopenharmony_ci	size_t mapsize;
792f08c3bdfSopenharmony_ci	uchar_t *readbuf;
793f08c3bdfSopenharmony_ci	unsigned mappages;
794f08c3bdfSopenharmony_ci	unsigned pagesize = sysconf(_SC_PAGE_SIZE);
795f08c3bdfSopenharmony_ci	int fd;
796f08c3bdfSopenharmony_ci	int cnt;
797f08c3bdfSopenharmony_ci	unsigned i, j;
798f08c3bdfSopenharmony_ci
799f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
800f08c3bdfSopenharmony_ci	if ((fd = open64(file, O_RDONLY)) == -1) {
801f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
802f08c3bdfSopenharmony_ci	if ((fd = open(file, O_RDONLY)) == -1) {
803f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
804f08c3bdfSopenharmony_ci		perror("open error");
805f08c3bdfSopenharmony_ci		anyfail();
806f08c3bdfSopenharmony_ci	}
807f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
808f08c3bdfSopenharmony_ci	if (fstat64(fd, &statbuf) == -1) {
809f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
810f08c3bdfSopenharmony_ci	if (fstat(fd, &statbuf) == -1) {
811f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
812f08c3bdfSopenharmony_ci		perror("stat error");
813f08c3bdfSopenharmony_ci		anyfail();
814f08c3bdfSopenharmony_ci	}
815f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
816f08c3bdfSopenharmony_ci	if (lseek64(fd, sparseoffset, SEEK_SET) < 0) {
817f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
818f08c3bdfSopenharmony_ci	if (lseek(fd, sparseoffset, SEEK_SET) < 0) {
819f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
820f08c3bdfSopenharmony_ci		perror("lseek");
821f08c3bdfSopenharmony_ci		exit(1);
822f08c3bdfSopenharmony_ci	}
823f08c3bdfSopenharmony_ci
824f08c3bdfSopenharmony_ci	readbuf = malloc(pagesize);
825f08c3bdfSopenharmony_ci
826f08c3bdfSopenharmony_ci	if (statbuf.st_size - sparseoffset > SIZE_MAX) {
827f08c3bdfSopenharmony_ci		fprintf(stderr, "size_t overflow when setting up map\n");
828f08c3bdfSopenharmony_ci		exit(1);
829f08c3bdfSopenharmony_ci	}
830f08c3bdfSopenharmony_ci	mapsize = (size_t) (statbuf.st_size - sparseoffset);
831f08c3bdfSopenharmony_ci	mappages = roundup(mapsize, pagesize) / pagesize;
832f08c3bdfSopenharmony_ci
833f08c3bdfSopenharmony_ci	for (i = 0; i < mappages; i++) {
834f08c3bdfSopenharmony_ci		cnt = read(fd, (char *)readbuf, pagesize);
835f08c3bdfSopenharmony_ci		if (cnt == -1) {
836f08c3bdfSopenharmony_ci			perror("read error");
837f08c3bdfSopenharmony_ci			close(fd);
838f08c3bdfSopenharmony_ci			return 0;
839f08c3bdfSopenharmony_ci		} else if (cnt != pagesize) {
840f08c3bdfSopenharmony_ci			/*
841f08c3bdfSopenharmony_ci			 *  Okay if at last page in file...
842f08c3bdfSopenharmony_ci			 */
843f08c3bdfSopenharmony_ci			if ((i * pagesize) + cnt != mapsize) {
844f08c3bdfSopenharmony_ci				(void)fprintf(stderr, "read %d of %ld bytes\n",
845f08c3bdfSopenharmony_ci					      (i * pagesize) + cnt,
846f08c3bdfSopenharmony_ci					      (long)mapsize);
847f08c3bdfSopenharmony_ci				close(fd);
848f08c3bdfSopenharmony_ci				return 0;
849f08c3bdfSopenharmony_ci			}
850f08c3bdfSopenharmony_ci		}
851f08c3bdfSopenharmony_ci		/*
852f08c3bdfSopenharmony_ci		 *  Compare read bytes of data.
853f08c3bdfSopenharmony_ci		 *  May have zeros from map extend...
854f08c3bdfSopenharmony_ci		 */
855f08c3bdfSopenharmony_ci		for (j = 0; j < cnt; j++) {
856f08c3bdfSopenharmony_ci			if (expbuf[j] != readbuf[j] && readbuf[j] != 0) {
857f08c3bdfSopenharmony_ci				(void)fprintf(stderr,
858f08c3bdfSopenharmony_ci					      "read bad data: exp %c got %c",
859f08c3bdfSopenharmony_ci					      expbuf[j], readbuf[j]);
860f08c3bdfSopenharmony_ci#ifdef LARGE_FILE
861f08c3bdfSopenharmony_ci				(void)fprintf(stderr, ", pg %d off %d, "
862f08c3bdfSopenharmony_ci					      "(fsize %Ld)\n", i, j,
863f08c3bdfSopenharmony_ci					      statbuf.st_size);
864f08c3bdfSopenharmony_ci#else /* LARGE_FILE */
865f08c3bdfSopenharmony_ci				(void)fprintf(stderr, ", pg %d off %d, "
866f08c3bdfSopenharmony_ci					      "(fsize %ld)\n", i, j,
867f08c3bdfSopenharmony_ci					      statbuf.st_size);
868f08c3bdfSopenharmony_ci#endif /* LARGE_FILE */
869f08c3bdfSopenharmony_ci				close(fd);
870f08c3bdfSopenharmony_ci				return 0;
871f08c3bdfSopenharmony_ci			}
872f08c3bdfSopenharmony_ci		}
873f08c3bdfSopenharmony_ci	}
874f08c3bdfSopenharmony_ci
875f08c3bdfSopenharmony_ci	close(fd);
876f08c3bdfSopenharmony_ci	return 1;
877f08c3bdfSopenharmony_ci}
878f08c3bdfSopenharmony_ci
879f08c3bdfSopenharmony_ci /*ARGSUSED*/ void finish(int sig)
880f08c3bdfSopenharmony_ci{
881f08c3bdfSopenharmony_ci	finished++;
882f08c3bdfSopenharmony_ci	/* finish nicely and check the file contents */
883f08c3bdfSopenharmony_ci}
884f08c3bdfSopenharmony_ci
885f08c3bdfSopenharmony_ci /*ARGSUSED*/ void clean_up_file(int sig)
886f08c3bdfSopenharmony_ci{
887f08c3bdfSopenharmony_ci	if (!leavefile)
888f08c3bdfSopenharmony_ci		(void)unlink(filename);
889f08c3bdfSopenharmony_ci	_exit(1);
890f08c3bdfSopenharmony_ci}
891f08c3bdfSopenharmony_ci
892f08c3bdfSopenharmony_civoid clean_mapper(int sig)
893f08c3bdfSopenharmony_ci{
894f08c3bdfSopenharmony_ci	if (fd_mapper)
895f08c3bdfSopenharmony_ci		close(fd_mapper);
896f08c3bdfSopenharmony_ci	munmap(maddr_mapper, mapsize_mapper);
897f08c3bdfSopenharmony_ci	_exit(0);
898f08c3bdfSopenharmony_ci}
899f08c3bdfSopenharmony_ci
900f08c3bdfSopenharmony_civoid clean_writer(int sig)
901f08c3bdfSopenharmony_ci{
902f08c3bdfSopenharmony_ci	if (fd_writer)
903f08c3bdfSopenharmony_ci		close(fd_writer);
904f08c3bdfSopenharmony_ci	_exit(0);
905f08c3bdfSopenharmony_ci}
906f08c3bdfSopenharmony_ci
907f08c3bdfSopenharmony_ciunsigned int initrand(void)
908f08c3bdfSopenharmony_ci{
909f08c3bdfSopenharmony_ci	unsigned int seed;
910f08c3bdfSopenharmony_ci
911f08c3bdfSopenharmony_ci	/*
912f08c3bdfSopenharmony_ci	 *  Initialize random seed...  Got this from a test written
913f08c3bdfSopenharmony_ci	 *  by scooter:
914f08c3bdfSopenharmony_ci	 *      Use srand/rand to diffuse the information from the
915f08c3bdfSopenharmony_ci	 *      time and pid.  If you start several processes, then
916f08c3bdfSopenharmony_ci	 *      the time and pid information don't provide much
917f08c3bdfSopenharmony_ci	 *      variation.
918f08c3bdfSopenharmony_ci	 */
919f08c3bdfSopenharmony_ci	srand((unsigned int)getpid());
920f08c3bdfSopenharmony_ci	seed = rand();
921f08c3bdfSopenharmony_ci	srand((unsigned int)time(NULL));
922f08c3bdfSopenharmony_ci	seed = (seed ^ rand()) % 100000;
923f08c3bdfSopenharmony_ci	srand48((long int)seed);
924f08c3bdfSopenharmony_ci	return (seed);
925f08c3bdfSopenharmony_ci}
926f08c3bdfSopenharmony_ci
927f08c3bdfSopenharmony_ci/*****  LTP Port        *****/
928f08c3bdfSopenharmony_civoid ok_exit(void)
929f08c3bdfSopenharmony_ci{
930f08c3bdfSopenharmony_ci	tst_resm(TPASS, "Test passed");
931f08c3bdfSopenharmony_ci	tst_rmdir();
932f08c3bdfSopenharmony_ci	tst_exit();
933f08c3bdfSopenharmony_ci}
934f08c3bdfSopenharmony_ci
935f08c3bdfSopenharmony_ciint anyfail(void)
936f08c3bdfSopenharmony_ci{
937f08c3bdfSopenharmony_ci	tst_brkm(TFAIL, tst_rmdir, "Test failed");
938f08c3bdfSopenharmony_ci}
939f08c3bdfSopenharmony_ci
940f08c3bdfSopenharmony_ci/*****  **      **      *****/
941