Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/user/testbin/dirconc/dirconc.c
734 views
1
/*
2
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3
* The President and Fellows of Harvard College.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the University nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
/*
31
* Concurrent directory operations test.
32
*
33
* Your system should survive this (without leaving a corrupted file
34
* system behind) once the file system assignment is complete.
35
*/
36
37
#include <sys/types.h>
38
#include <sys/wait.h>
39
#include <sys/stat.h>
40
#include <errno.h>
41
#include <stdio.h>
42
#include <unistd.h>
43
#include <stdlib.h>
44
#include <stdarg.h>
45
#include <string.h>
46
47
#define NTRIES 100 /* loop count */
48
#define NPROCS 5 /* actually totals 4x this +1 processes */
49
50
#define TESTDIR "dirconc"
51
#define NNAMES 4
52
#define NAMESIZE 32
53
54
////////////////////////////////////////////////////////////
55
56
static const char *const names[NNAMES] = {
57
"aaaa",
58
"bbbb",
59
"cccc",
60
"dddd",
61
};
62
63
static
64
void
65
choose_name(char *buf, size_t len)
66
{
67
const char *a, *b, *c;
68
69
a = names[random()%NNAMES];
70
if (random()%2==0) {
71
snprintf(buf, len, "%s", a);
72
return;
73
}
74
b = names[random()%NNAMES];
75
if (random()%2==0) {
76
snprintf(buf, len, "%s/%s", a, b);
77
return;
78
}
79
c = names[random()%NNAMES];
80
snprintf(buf, len, "%s/%s/%s", a, b, c);
81
}
82
83
////////////////////////////////////////////////////////////
84
85
/*
86
* The purpose of this is to be atomic. In our world, straight
87
* printf tends not to be.
88
*/
89
static
90
void
91
#ifdef __GNUC__
92
__attribute__((__format__(__printf__, 1, 2)))
93
#endif
94
say(const char *fmt, ...)
95
{
96
char buf[512];
97
va_list ap;
98
va_start(ap, fmt);
99
vsnprintf(buf, sizeof(buf), fmt, ap);
100
va_end(ap);
101
write(STDOUT_FILENO, buf, strlen(buf));
102
}
103
104
////////////////////////////////////////////////////////////
105
106
static
107
void
108
dorename(const char *name1, const char *name2)
109
{
110
if (rename(name1, name2) < 0) {
111
switch (errno) {
112
case ENOENT:
113
case ENOTEMPTY:
114
case EINVAL:
115
break;
116
default:
117
say("pid %d: rename %s -> %s: %s\n",
118
getpid(), name1, name2, strerror(errno));
119
break;
120
}
121
}
122
}
123
124
static
125
void
126
domkdir(const char *name)
127
{
128
if (mkdir(name, 0775)<0) {
129
switch (errno) {
130
case ENOENT:
131
case EEXIST:
132
break;
133
default:
134
say("pid %d: mkdir %s: %s\n",
135
getpid(), name, strerror(errno));
136
break;
137
}
138
}
139
}
140
141
static
142
void
143
dormdir(const char *name)
144
{
145
if (rmdir(name)<0) {
146
switch (errno) {
147
case ENOENT:
148
case ENOTEMPTY:
149
break;
150
default:
151
say("pid %d: rmdir %s: %s\n",
152
getpid(), name, strerror(errno));
153
break;
154
}
155
}
156
}
157
158
static
159
void
160
cleanup_rmdir(const char *name)
161
{
162
if (rmdir(name)<0) {
163
switch (errno) {
164
case ENOENT:
165
break;
166
default:
167
say("cleanup (pid %d): rmdir %s: %s\n",
168
getpid(), name, strerror(errno));
169
break;
170
}
171
}
172
}
173
174
////////////////////////////////////////////////////////////
175
176
static
177
void
178
rename_proc(void)
179
{
180
char name1[NAMESIZE], name2[NAMESIZE];
181
int ct;
182
183
for (ct=0; ct<NTRIES; ct++) {
184
choose_name(name1, sizeof(name1));
185
choose_name(name2, sizeof(name2));
186
say("pid %2d: rename %s -> %s\n", (int)getpid(), name1, name2);
187
dorename(name1, name2);
188
}
189
}
190
191
static
192
void
193
mkdir_proc(void)
194
{
195
char name[NAMESIZE];
196
int ct;
197
198
for (ct=0; ct<NTRIES; ct++) {
199
choose_name(name, sizeof(name));
200
say("pid %2d: mkdir %s\n", (int)getpid(), name);
201
domkdir(name);
202
}
203
}
204
205
static
206
void
207
rmdir_proc(void)
208
{
209
char name[NAMESIZE];
210
int ct;
211
212
for (ct=0; ct<NTRIES; ct++) {
213
choose_name(name, sizeof(name));
214
say("pid %2d: rmdir %s\n", (int)getpid(), name);
215
dormdir(name);
216
}
217
}
218
219
////////////////////////////////////////////////////////////
220
221
static
222
pid_t
223
dofork(void (*func)(void))
224
{
225
pid_t pid;
226
227
pid = fork();
228
if (pid < 0) {
229
say("fork: %s\n", strerror(errno));
230
return -1;
231
}
232
if (pid == 0) {
233
/* child */
234
func();
235
exit(0);
236
}
237
return pid;
238
}
239
240
static
241
void
242
run(void)
243
{
244
pid_t pids[NPROCS*4], wp;
245
int i, status;
246
247
for (i=0; i<NPROCS; i++) {
248
pids[i*4] = dofork(mkdir_proc);
249
pids[i*4+1] = dofork(mkdir_proc);
250
pids[i*4+2] = dofork(rename_proc);
251
pids[i*4+3] = dofork(rmdir_proc);
252
}
253
254
for (i=0; i<NPROCS*4; i++) {
255
if (pids[i]>=0) {
256
wp = waitpid(pids[i], &status, 0);
257
if (wp<0) {
258
say("waitpid %d: %s\n", (int) pids[i],
259
strerror(errno));
260
}
261
else if (WIFSIGNALED(status)) {
262
say("pid %d: signal %d\n", (int) pids[i],
263
WTERMSIG(status));
264
}
265
else if (WIFEXITED(status) && WEXITSTATUS(status)!=0) {
266
say("pid %d: exit %d\n", (int) pids[i],
267
WEXITSTATUS(status));
268
}
269
}
270
}
271
}
272
273
////////////////////////////////////////////////////////////
274
275
static
276
void
277
setup(const char *fs)
278
{
279
if (chdir(fs)<0) {
280
say("chdir: %s: %s\n", fs, strerror(errno));
281
exit(1);
282
}
283
if (mkdir(TESTDIR, 0775)<0) {
284
say("mkdir: %s: %s\n", TESTDIR, strerror(errno));
285
exit(1);
286
}
287
if (chdir(TESTDIR)<0) {
288
say("chdir: %s: %s\n", TESTDIR, strerror(errno));
289
exit(1);
290
}
291
}
292
293
static
294
void
295
recursive_cleanup(const char *sofar, int depth)
296
{
297
char buf[NAMESIZE*32];
298
int i;
299
300
for (i=0; i<NNAMES; i++) {
301
snprintf(buf, sizeof(buf), "%s/%s", sofar, names[i]);
302
if (rmdir(buf)<0) {
303
if (errno==ENOTEMPTY) {
304
recursive_cleanup(buf, depth+1);
305
cleanup_rmdir(buf);
306
}
307
else if (errno!=ENOENT) {
308
say("cleanup (pid %d): rmdir %s: %s\n",
309
getpid(), buf, strerror(errno));
310
}
311
}
312
}
313
}
314
315
static
316
void
317
cleanup(void)
318
{
319
recursive_cleanup(".", 0);
320
321
chdir("..");
322
cleanup_rmdir(TESTDIR);
323
}
324
325
////////////////////////////////////////////////////////////
326
327
int
328
main(int argc, char *argv[])
329
{
330
const char *fs;
331
long seed = 0;
332
333
say("Concurrent directory ops test\n");
334
335
if (argc==0 || argv==NULL) {
336
say("Warning: argc is 0 - assuming you mean to run on lhd1: "
337
"with seed 0\n");
338
fs = "lhd1:";
339
}
340
else if (argc==2) {
341
fs = argv[1];
342
}
343
else if (argc==3) {
344
fs = argv[1];
345
seed = atoi(argv[2]);
346
}
347
else {
348
say("Usage: dirconc filesystem [random-seed]\n");
349
exit(1);
350
}
351
352
srandom(seed);
353
setup(fs);
354
say("Starting in %s/%s\n", fs, TESTDIR);
355
356
run();
357
358
say("Cleaning up\n");
359
cleanup();
360
361
return 0;
362
}
363
364