]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/test/stress2/misc/fcntl.sh
contrib/bc: update to version 5.1.1
[FreeBSD/FreeBSD.git] / tools / test / stress2 / misc / fcntl.sh
1 #!/bin/sh
2
3 #
4 # Copyright (c) 2014 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 # fcntl(2) locking scenario. No problems seen.
30
31 . ../default.cfg
32
33 here=`pwd`
34 cd /tmp
35 sed '1,/^EOF/d' < $here/$0 > fcntl.c
36 mycc -o fcntl -Wall -Wextra -O0 -g fcntl.c || exit 1
37 rm -f fcntl.c
38
39 mkdir -p $RUNDIR
40 cd $RUNDIR
41 /tmp/fcntl
42 status=$?
43
44 rm -f /tmp/fcntl
45 exit $status
46 EOF
47 #include <sys/types.h>
48 #include <err.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <signal.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <sys/wait.h>
56 #include <unistd.h>
57
58 #define PARALLEL 16
59 #define N 4096
60
61 static volatile sig_atomic_t completed;
62 const char name[] = "work";
63 int fd;
64
65 static void
66 ahandler(int s __unused)
67 {
68         unlink(name);
69         _exit(1);
70 }
71
72 static void
73 handler(int s __unused)
74 {
75         completed++;
76 }
77
78 void
79 add(int n, int increment)
80 {
81         struct flock fl;
82         off_t pos;
83         long val, oval;
84         int r;
85
86         pos = n * sizeof(val);
87         memset(&fl, 0, sizeof(fl));
88         fl.l_start = pos;
89         fl.l_len = sizeof(val);
90         fl.l_type = F_WRLCK;
91         fl.l_whence = SEEK_SET;
92
93         while (fcntl(fd, F_SETLK, &fl) < 0) {
94                 if (errno != EAGAIN)
95                         err(1, "F_SETLK (child)");
96                 usleep(100);
97         }
98
99         if (lseek(fd, pos, SEEK_SET) == -1)
100                 err(1, "lseek");
101         oval = 999999;
102         while ((r = read(fd, &val, sizeof(val)) != sizeof(val))) {
103                 if (r == -1 && errno != EAGAIN)
104                         err(1, "read");
105                 if (lseek(fd, pos, SEEK_SET) == -1)
106                         err(1, "lseek");
107         }
108         oval = val;
109         val = val + increment;
110 #if defined(DEBUG)
111         fprintf(stderr, "add(%d, %d) @ pos %ld: %ld = %ld + %d\n",
112             n, increment, (long)pos, val, oval, increment);
113 #endif
114         if (lseek(fd, pos, SEEK_SET) == -1)
115                 err(1, "lseek");
116         while ((r = write(fd, &val, sizeof(val)) != sizeof(val))) {
117                 if (r == -1 && errno != EAGAIN)
118                         err(1, "write");
119                 if (lseek(fd, pos, SEEK_SET) == -1)
120                         err(1, "lseek");
121         }
122
123         fl.l_type = F_UNLCK;
124         if (fcntl(fd, F_SETLK, &fl) < 0)
125                 err(1, "F_UNLCK");
126
127 }
128
129 void
130 up(void)
131 {
132         int flags, i;
133
134         /* Need to re-open after a fork() */
135         close(fd);
136         if ((fd = open(name, O_RDWR)) == -1)
137                 err(1, "open(%s)", name);
138         if ((flags = fcntl(fd, F_GETFL)) == -1)
139                 err(1, "fcntl(%d, T_GETFL)", fd);
140         flags |= O_NONBLOCK;
141         if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
142                 err(1, "fcntl(%d, T_SETFL, %d)", fd, flags);
143
144         for (i = 0; i < N; i++)
145                 add(i, 1);
146
147         kill(getppid(), SIGHUP);
148         while (access("work", R_OK) == 0)
149                 usleep(100);
150
151         _exit(0);
152 }
153
154 void
155 down(void)
156 {
157         int flags, i;
158
159         close(fd);
160         if ((fd = open(name, O_RDWR)) == -1)
161                 err(1, "open(%s)", name);
162         if ((flags = fcntl(fd, F_GETFL)) == -1)
163                 err(1, "fcntl(%d, T_GETFL)", fd);
164         flags |= O_NONBLOCK;
165         if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
166                 err(1, "fcntl(%d, T_SETFL, %d)", fd, flags);
167
168         for (i = 0; i < N; i++)
169                 add(i, -1);
170
171         kill(getppid(), SIGHUP);
172         while (access("work", R_OK) == 0)
173                 usleep(100);
174
175         _exit(0);
176 }
177
178 int
179 main(void)
180 {
181         int flags, i;
182         long val, sum;
183         off_t len;
184
185         signal(SIGHUP, handler);
186         signal(SIGALRM, ahandler);
187         alarm(300);
188         if ((fd = open(name, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1)
189                 err(1, "open(%s)", name);
190         len = N * sizeof(val);
191         if (ftruncate(fd, len) == -1)
192                 err(1, "ftruncate");
193
194         if ((flags = fcntl(fd, F_GETFL)) == -1)
195                 err(1, "fcntl(%d, T_GETFL)", fd);
196         flags |= O_NONBLOCK;
197         if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
198                 err(1, "fcntl(%d, T_SETFL, %d)", fd, flags);
199
200         for (i = 0; i < PARALLEL; i++) {
201                 if (fork() == 0)
202                         up();
203         }
204         for (i = 0; i < PARALLEL; i++) {
205                 if (fork() == 0)
206                         down();
207         }
208
209         while (completed != PARALLEL * 2)
210                 usleep(200);
211
212         if (lseek(fd, 0, SEEK_SET) == -1)
213                 err(1, "lseek");
214         sum = 0;
215         for (i = 0; i < N; i++) {
216                 if (read(fd, &val, sizeof(val)) != sizeof(val))
217                         err(1, "Final read");
218                 if (val != 0)
219                         fprintf(stderr, "index %d: %ld\n", i, val);
220                 sum += val;
221         }
222         if (sum != 0)
223                 fprintf(stderr, "FAIL\n");
224         unlink(name);
225
226         for (i = 0; i < PARALLEL; i++) {
227                 wait(NULL);
228                 wait(NULL);
229         }
230
231         close(fd);
232
233         return (sum != 0);
234 }