Bring in FreeBSD's stress2 stress testing suite.
[dragonfly.git] / test / stress / stress2 / misc / datamove.sh
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 # $FreeBSD$
29 #
30
31 # There is a well-known problem in FreeBSD, caused by allowing page faults
32 # while doing filesystem data move to or from userspace during read(2) and
33 # write(2). The issue is that if the userspace address being read or write
34 # from/to is backed by the mapping of the same file we are doing i/o to,
35 # we deadlock.
36
37 # Test scenario by ups
38
39 [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
40
41 here=`pwd`
42 cd /tmp
43 sed '1,/^EOF/d' < $here/$0 > dl.c
44 cc -o dl -Wall dl.c
45 rm -f dl.c
46
47 n=5
48 old=`sysctl vm.old_msync | awk '{print $NF}'`
49 sysctl vm.old_msync=1
50 for i in `jot $n`; do
51         mkdir -p /tmp/dl.dir.$i
52         cd /tmp/dl.dir.$i
53         /tmp/dl &
54 done
55 cd /tmp
56 for i in `jot $n`; do
57         wait
58 done
59 for i in `jot $n`; do
60         rm -rf /tmp/dl.dir.$i
61 done
62 sysctl vm.old_msync=$old
63
64 rm -rf /tmp/dl
65 exit 0
66 EOF
67 #include <sys/types.h>
68 #include <unistd.h>
69 #include <sys/stat.h>
70 #include <fcntl.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <sys/mman.h>
74
75
76 int prepareFile(char* filename,int* fdp);
77 int mapBuffer(char** bufferp,int fd1,int fd2);
78 int startIO(int fd,char *buffer);
79
80 int pagesize;
81
82 #define FILESIZE (32*1024)
83 char wbuffer[FILESIZE];
84
85 /* Create a FILESIZE sized file - then remove file data from the cache*/
86 int prepareFile(char* filename,int* fdp)
87 {
88   int fd;
89   int len;
90   int status;
91   void *addr;
92
93   fd = open(filename,O_CREAT | O_TRUNC | O_RDWR,S_IRWXU);
94   if (fd == -1)
95     {
96       perror("Creating file");
97       return fd;
98     }
99
100   len = write(fd,wbuffer,FILESIZE);
101   if (len < 0)
102     {
103       perror("Write failed");
104       return 1;
105     }
106
107   status = fsync(fd);
108    if (status != 0)
109     {
110         perror("fsync failed");
111         return 1;
112     }
113
114   addr = mmap(NULL,FILESIZE, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);
115   if (addr == MAP_FAILED)
116     {
117       perror("Mmap failed");
118       return 1;
119     }
120
121   status = msync(addr,FILESIZE,MS_INVALIDATE | MS_SYNC);
122   if (status != 0)
123     {
124         perror("Msync failed");
125         return 1;
126     }
127
128   munmap(addr,FILESIZE);
129
130   *fdp = fd;
131   return 0;
132 }
133
134
135 /* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
136 int mapBuffer(char** bufferp,int fd1,int fd2)
137 {
138   void* addr;
139   char *buffer;
140
141   addr = mmap(NULL,pagesize*2, PROT_READ | PROT_WRITE , MAP_SHARED, fd1, 0);
142   if (addr == MAP_FAILED)
143     {
144       perror("Mmap failed");
145       return 1;
146     }
147
148   buffer = addr;
149   addr = mmap(buffer + pagesize,pagesize, PROT_READ | PROT_WRITE , MAP_FIXED |
150 MAP_SHARED, fd2, 0);
151
152   if (addr == MAP_FAILED)
153     {
154       perror("Mmap2 failed");
155       return 1;
156     }
157   *bufferp = buffer;
158   return 0;
159 }
160
161
162 int startIO(int fd,char *buffer)
163 {
164   ssize_t len;
165   len = write(fd,buffer,2*pagesize);
166   if (len == -1)
167     {
168       perror("write failed");
169       return 1;
170     }
171   return 0;
172 }
173
174
175 int main(int argc,char *argv[],char *envp[])
176 {
177
178   int fdA,fdB,fdDelayA,fdDelayB;
179   int status;
180   char *bufferA,*bufferB;
181   pid_t pid;
182
183   pagesize = getpagesize();
184
185   if ((prepareFile("A",&fdA))
186       || (prepareFile("B",&fdB))
187       || (prepareFile("DelayA",&fdDelayA))
188       || (prepareFile("DelayB",&fdDelayB))
189       || (mapBuffer(&bufferA,fdDelayA,fdB))
190       || (mapBuffer(&bufferB,fdDelayB,fdA)))
191     exit(1);
192
193   pid = fork();
194
195   if (pid == 0)
196     {
197       status = startIO(fdA,bufferA);
198       exit(status);
199     }
200
201   if (pid == -1)
202     {
203       exit(1);
204     }
205   status = startIO(fdB,bufferB);
206   exit(status);
207
208 }