xref: /freebsd/tools/test/stress2/misc/datamove5.sh (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1#!/bin/sh
2
3#
4# Copyright (c) 2016 EMC Corp.
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# Variation of the datamove2.sh, using NULLFS
30# No problems seen.
31
32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
33
34. ../default.cfg
35
36here=`pwd`
37cd /tmp
38sed '1,/^EOF/d' < $here/$0 > datamove5.c
39mycc -o datamove5 -Wall -Wextra -O2 -g datamove5.c
40rm -f datamove5.c
41
42mp1=$mntpoint
43mp2=${mntpoint}2
44[ -d $mp2 ] || mkdir $mp2
45
46mount | grep -wq $mp2 && umount $mp2
47mount | grep -wq $mp1 && umount $mp1
48mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
49mdconfig -a -t swap -s 2g -u $mdstart || exit 1
50newfs $newfs_flags md$mdstart > /dev/null
51mount /dev/md$mdstart $mp1
52
53mount -t nullfs $opt $mp1 $mp2
54chmod 777 $mp2
55
56for i in `jot 5`; do
57	su $testuser -c "cd $mp2; /tmp/datamove5"
58done
59
60while mount | grep -wq $mp2;  do
61	umount $mp2 || sleep 1
62done
63while mount | grep $mp1 | grep -q /dev/md; do
64	umount $mp1 || sleep 1
65done
66mdconfig -d -u $mdstart
67
68rm -rf /tmp/datamove5
69exit 0
70EOF
71/*-
72 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org>
73 * All rights reserved.
74 *
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
77 * are met:
78 * 1. Redistributions of source code must retain the above copyright
79 *    notice unmodified, this list of conditions, and the following
80 *    disclaimer.
81 * 2. Redistributions in binary form must reproduce the above copyright
82 *    notice, this list of conditions and the following disclaimer in the
83 *    documentation and/or other materials provided with the distribution.
84 *
85 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
86 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
87 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
88 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
89 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
90 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
91 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
92 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
93 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
94 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
95 */
96
97#include <err.h>
98#include <fcntl.h>
99#include <stdio.h>
100#include <stdlib.h>
101#include <sys/mman.h>
102#include <sys/stat.h>
103#include <sys/types.h>
104#include <sys/wait.h>
105#include <unistd.h>
106
107int	prepareFile(char *filename, int *fdp);
108int	mapBuffer  (char **bufferp, int fd1, int fd2);
109int	startIO    (int fd, char *buffer);
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(filename);
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	if (munmap(addr, FILESIZE) == -1) {
151		perror("munmap failed");
152		return 1;
153	}
154
155	*fdp = fd;
156	return 0;
157}
158
159/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
160int
161mapBuffer(char **bufferp, int fd1, int fd2)
162{
163	void *addr;
164	char *buffer;
165
166	addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
167	if (addr == MAP_FAILED) {
168		perror("Mmap failed");
169		return 1;
170	}
171	buffer = addr;
172	addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED |
173		    MAP_SHARED, fd2, 0);
174
175	if (addr == MAP_FAILED) {
176		perror("Mmap2 failed");
177		return 1;
178	}
179	*bufferp = buffer;
180	return 0;
181}
182
183void
184unmapBuffer(char *bufferp)
185{
186	if (munmap(bufferp, pagesize * 2) == -1)
187		err(1, "unmap 1. buffer");
188	/*
189	   The following unmaps something random, which could trigger:
190	   Program received signal SIGSEGV, Segmentation fault.
191	   free (cp=0x28070000) at /usr/src/libexec/rtld-elf/malloc.c:311
192	*/
193
194#if 0
195	if (munmap(bufferp + pagesize * 2, pagesize * 2) == -1)
196		err(1, "unmap 2. buffer");
197#endif
198}
199
200int
201startIO(int fd, char *buffer)
202{
203	ssize_t	len;
204
205	len = write(fd, buffer, 2 * pagesize);
206	if (len == -1) {
207		perror("write failed");
208		return 1;
209	}
210	return 0;
211}
212
213int
214main()
215{
216
217	int	fdA, fdB, fdDelayA, fdDelayB;
218	int	status;
219	int	i;
220	char	*bufferA, *bufferB;
221	pid_t	pid;
222
223	pagesize = getpagesize();
224
225	for (i = 0; i < 1000; i++) {
226		if ((prepareFile("A", &fdA))
227		    || (prepareFile("B", &fdB))
228		    || (prepareFile("DelayA", &fdDelayA))
229		    || (prepareFile("DelayB", &fdDelayB))
230		    || (mapBuffer(&bufferA, fdDelayA, fdB))
231		    || (mapBuffer(&bufferB, fdDelayB, fdA)))
232			exit(1);
233
234		pid = fork();
235
236		if (pid == 0) {
237			status = startIO(fdA, bufferA);
238			exit(status);
239		}
240		if (pid == -1) {
241			perror("fork");
242			exit(1);
243		}
244		status = startIO(fdB, bufferB);
245		if (wait(&status) == -1)
246			err(1, "wait");
247
248		close(fdA);
249		close(fdB);
250		close(fdDelayA);
251		close(fdDelayB);
252		unmapBuffer(bufferA);
253		unmapBuffer(bufferB);
254		unlink("A");
255		unlink("B");
256		unlink("DelayA");
257		unlink("DelayB");
258	}
259	exit(status);
260
261}
262