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