xref: /freebsd/tools/test/stress2/misc/datamove3.sh (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1#!/bin/sh
2
3#
4# Copyright (c) 2009 Peter Holm <pho@FreeBSD.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# Threaded variation of datamove.sh
30
31# Based on a test scenario by ups and suggestions by kib
32
33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
34
35. ../default.cfg
36
37here=`pwd`
38cd /tmp
39sed '1,/^EOF/d' < $here/$0 > datamove3.c
40mycc -o datamove3 -Wall datamove3.c -lpthread
41rm -f datamove3.c
42
43n=5
44old=`sysctl vm.old_msync | awk '{print $NF}'`
45sysctl vm.old_msync=1
46for i in `jot $n`; do
47	mkdir -p /tmp/datamove3.dir.$i
48	cd /tmp/datamove3.dir.$i
49	/tmp/datamove3 &
50done
51cd /tmp
52for i in `jot $n`; do
53	wait
54done
55for i in `jot $n`; do
56	rm -rf /tmp/datamove3.dir.$i
57done
58sysctl vm.old_msync=$old
59
60rm -rf /tmp/datamove3
61exit 0
62EOF
63/*-
64 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org>
65 * All rights reserved.
66 *
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
69 * are met:
70 * 1. Redistributions of source code must retain the above copyright
71 *    notice unmodified, this list of conditions, and the following
72 *    disclaimer.
73 * 2. Redistributions in binary form must reproduce the above copyright
74 *    notice, this list of conditions and the following disclaimer in the
75 *    documentation and/or other materials provided with the distribution.
76 *
77 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
78 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
79 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
80 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
81 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
82 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
83 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
84 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
85 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
86 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
87 */
88
89#include <err.h>
90#include <fcntl.h>
91#include <pthread.h>
92#include <stdio.h>
93#include <stdio.h>
94#include <stdlib.h>
95#include <string.h>
96#include <sys/mman.h>
97#include <sys/stat.h>
98#include <sys/types.h>
99#include <unistd.h>
100
101struct args {
102	char *bp;
103	int fd1;
104	int fd2;
105} a[2];
106
107int prepareFile(char *, int *);
108void * mapBuffer(void *);
109int startIO(int, char *);
110
111int pagesize;
112
113#define FILESIZE (32*1024)
114char wbuffer   [FILESIZE];
115
116/* Create a FILESIZE sized file - then remove file data from the cache */
117int
118prepareFile(char *filename, int *fdp)
119{
120	int fd;
121	int len;
122	int status;
123	void *addr;
124
125	fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
126	if (fd == -1) {
127		perror("Creating file");
128		return fd;
129	}
130	len = write(fd, wbuffer, FILESIZE);
131	if (len < 0) {
132		perror("Write failed");
133		return 1;
134	}
135	status = fsync(fd);
136	if (status != 0) {
137		perror("fsync failed");
138		return 1;
139	}
140	addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
141	if (addr == MAP_FAILED) {
142		perror("Mmap failed");
143		return 1;
144	}
145	status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC);
146	if (status != 0) {
147		perror("Msync failed");
148		return 1;
149	}
150	munmap(addr, FILESIZE);
151
152	*fdp = fd;
153	return 0;
154}
155
156/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
157void *
158mapBuffer(void *ar)
159{
160	void *addr;
161	char *buffer;
162	int i;
163
164	i = (intptr_t)ar;
165	addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, a[i].fd1, 0);
166	if (addr == MAP_FAILED) {
167		err(1, "Mmap failed");
168	}
169	buffer = addr;
170	addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED |
171		    MAP_SHARED, a[i].fd2, 0);
172
173	if (addr == MAP_FAILED) {
174		err(1, "Mmap2 failed");
175	}
176	a[i].bp = buffer;
177	sleep(1);
178	return (NULL);
179}
180
181int
182startIO(int fd, char *buffer)
183{
184	ssize_t len;
185
186	len = write(fd, buffer, 2 * pagesize);
187	if (len == -1) {
188		warn("startIO(%d, %p): write failed", fd, buffer);
189		return 1;
190	}
191	return 0;
192}
193
194int
195main(void)
196{
197
198	int fdA, fdB, fdDelayA, fdDelayB;
199	int r, status;
200	char *bufferA, *bufferB;
201	pid_t pid;
202	pthread_t threads[2];
203
204	pagesize = getpagesize();
205
206	if ((prepareFile("A", &fdA))
207	    || (prepareFile("B", &fdB))
208	    || (prepareFile("DelayA", &fdDelayA))
209	    || (prepareFile("DelayB", &fdDelayB)))
210		exit(1);
211
212	a[0].fd1 = fdDelayA;
213	a[0].fd2 = fdB;
214
215	a[1].fd1 = fdDelayB;
216	a[1].fd2 = fdA;
217
218	if ((r = pthread_create(&threads[0], NULL, mapBuffer, (void *)0)) != 0)
219		errc(1, r, "pthread_create()");
220	if ((r = pthread_create(&threads[1], NULL, mapBuffer, (void *)1)) != 0)
221		errc(1, r, "pthread_create()");
222
223	while (a[0].bp == NULL || a[1].bp == NULL)
224		pthread_yield();
225
226	bufferA = a[0].bp;
227	bufferB = a[1].bp;
228
229	pid = fork();
230
231	if (pid == 0) {
232		status = startIO(fdA, bufferA);
233		exit(status);
234	}
235	if (pid == -1) {
236		exit(1);
237	}
238	status = startIO(fdB, bufferB);
239	exit(status);
240
241}
242