xref: /freebsd/tools/test/stress2/misc/datamove5.sh (revision 29332c0dcee1e80c9fb871e06c3160bd5deb1b44)
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
50bsdlabel -w md$mdstart auto
51newfs $newfs_flags md${mdstart}$part > /dev/null
52mount /dev/md${mdstart}$part $mp1
53
54mount -t nullfs $opt $mp1 $mp2
55chmod 777 $mp2
56
57for i in `jot 5`; do
58	su $testuser -c "cd $mp2; /tmp/datamove5"
59done
60
61while mount | grep -wq $mp2;  do
62	umount $mp2 || sleep 1
63done
64while mount | grep $mp1 | grep -q /dev/md; do
65	umount $mp1 || sleep 1
66done
67mdconfig -d -u $mdstart
68
69rm -rf /tmp/datamove5
70exit 0
71EOF
72/*-
73 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org>
74 * All rights reserved.
75 *
76 * Redistribution and use in source and binary forms, with or without
77 * modification, are permitted provided that the following conditions
78 * are met:
79 * 1. Redistributions of source code must retain the above copyright
80 *    notice unmodified, this list of conditions, and the following
81 *    disclaimer.
82 * 2. Redistributions in binary form must reproduce the above copyright
83 *    notice, this list of conditions and the following disclaimer in the
84 *    documentation and/or other materials provided with the distribution.
85 *
86 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
87 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
88 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
89 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
90 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
91 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
92 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
93 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
94 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
95 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
96 */
97
98#include <err.h>
99#include <fcntl.h>
100#include <stdio.h>
101#include <stdlib.h>
102#include <sys/mman.h>
103#include <sys/stat.h>
104#include <sys/types.h>
105#include <sys/wait.h>
106#include <unistd.h>
107
108int	prepareFile(char *filename, int *fdp);
109int	mapBuffer  (char **bufferp, int fd1, int fd2);
110int	startIO    (int fd, char *buffer);
111
112int	pagesize;
113
114#define FILESIZE (32*1024)
115char	wbuffer   [FILESIZE];
116
117/* Create a FILESIZE sized file - then remove file data from the cache */
118int
119prepareFile(char *filename, int *fdp)
120{
121	int	fd;
122	int	len;
123	int	status;
124	void	*addr;
125
126	fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
127	if (fd == -1) {
128		perror(filename);
129		return fd;
130	}
131	len = write(fd, wbuffer, FILESIZE);
132	if (len < 0) {
133		perror("Write failed");
134		return 1;
135	}
136	status = fsync(fd);
137	if (status != 0) {
138		perror("fsync failed");
139		return 1;
140	}
141	addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
142	if (addr == MAP_FAILED) {
143		perror("Mmap failed");
144		return 1;
145	}
146	status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC);
147	if (status != 0) {
148		perror("Msync failed");
149		return 1;
150	}
151	if (munmap(addr, FILESIZE) == -1) {
152		perror("munmap failed");
153		return 1;
154	}
155
156	*fdp = fd;
157	return 0;
158}
159
160/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
161int
162mapBuffer(char **bufferp, int fd1, int fd2)
163{
164	void *addr;
165	char *buffer;
166
167	addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
168	if (addr == MAP_FAILED) {
169		perror("Mmap failed");
170		return 1;
171	}
172	buffer = addr;
173	addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED |
174		    MAP_SHARED, fd2, 0);
175
176	if (addr == MAP_FAILED) {
177		perror("Mmap2 failed");
178		return 1;
179	}
180	*bufferp = buffer;
181	return 0;
182}
183
184void
185unmapBuffer(char *bufferp)
186{
187	if (munmap(bufferp, pagesize * 2) == -1)
188		err(1, "unmap 1. buffer");
189	/*
190	   The following unmaps something random, which could trigger:
191	   Program received signal SIGSEGV, Segmentation fault.
192	   free (cp=0x28070000) at /usr/src/libexec/rtld-elf/malloc.c:311
193	*/
194
195#if 0
196	if (munmap(bufferp + pagesize * 2, pagesize * 2) == -1)
197		err(1, "unmap 2. buffer");
198#endif
199}
200
201int
202startIO(int fd, char *buffer)
203{
204	ssize_t	len;
205
206	len = write(fd, buffer, 2 * pagesize);
207	if (len == -1) {
208		perror("write failed");
209		return 1;
210	}
211	return 0;
212}
213
214int
215main()
216{
217
218	int	fdA, fdB, fdDelayA, fdDelayB;
219	int	status;
220	int	i;
221	char	*bufferA, *bufferB;
222	pid_t	pid;
223
224	pagesize = getpagesize();
225
226	for (i = 0; i < 1000; i++) {
227		if ((prepareFile("A", &fdA))
228		    || (prepareFile("B", &fdB))
229		    || (prepareFile("DelayA", &fdDelayA))
230		    || (prepareFile("DelayB", &fdDelayB))
231		    || (mapBuffer(&bufferA, fdDelayA, fdB))
232		    || (mapBuffer(&bufferB, fdDelayB, fdA)))
233			exit(1);
234
235		pid = fork();
236
237		if (pid == 0) {
238			status = startIO(fdA, bufferA);
239			exit(status);
240		}
241		if (pid == -1) {
242			perror("fork");
243			exit(1);
244		}
245		status = startIO(fdB, bufferB);
246		if (wait(&status) == -1)
247			err(1, "wait");
248
249		close(fdA);
250		close(fdB);
251		close(fdDelayA);
252		close(fdDelayB);
253		unmapBuffer(bufferA);
254		unmapBuffer(bufferB);
255		unlink("A");
256		unlink("B");
257		unlink("DelayA");
258		unlink("DelayB");
259	}
260	exit(status);
261
262}
263