Whamcloud - gitweb
34e855add45fdc985d1a785595f22a4282d98426
[fs/lustre-release.git] / lustre / tests / createdestroy.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/wait.h>
10 #include <time.h>
11 #include <sys/time.h>
12
13 int thread;
14
15 #define BAD_VERBOSE (-999999999)
16
17 #define difftime(a, b)                                          \
18         ((double)(a)->tv_sec - (b)->tv_sec +                    \
19          ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
20
21 static char *cmdname(char *func)
22 {
23         static char buf[512];
24
25         if (thread) {
26                 sprintf(buf, "%s-%d", func, thread);
27                 return buf;
28         }
29
30         return func;
31 }
32
33 static int be_verbose(int verbose, struct timeval *next_time,
34                       unsigned long num, unsigned long *next_num, int num_total)
35 {
36         struct timeval now;
37
38         if (!verbose)
39                 return 0;
40
41         if (next_time != NULL)
42                 gettimeofday(&now, NULL);
43
44         /* A positive verbosity means to print every X iterations */
45         if (verbose > 0 &&
46             (next_num == NULL || num >= *next_num || num >= num_total)) {
47                 *next_num += verbose;
48                 if (next_time) {
49                         next_time->tv_sec = now.tv_sec - verbose;
50                         next_time->tv_usec = now.tv_usec;
51                 }
52                 return 1;
53         }
54
55         /* A negative verbosity means to print at most each X seconds */
56         if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
57                 next_time->tv_sec = now.tv_sec - verbose;
58                 next_time->tv_usec = now.tv_usec;
59                 if (next_num)
60                         *next_num = num;
61                 return 1;
62         }
63
64         return 0;
65 }
66
67 static int get_verbose(char *func, const char *arg)
68 {
69         int verbose;
70         char *end;
71
72         if (!arg || arg[0] == 'v')
73                 verbose = 1;
74         else if (arg[0] == 's' || arg[0] == 'q')
75                 verbose = 0;
76         else {
77                 verbose = (int)strtoul(arg, &end, 0);
78                 if (*end) {
79                         fprintf(stderr, "%s: error: bad verbose option '%s'\n",
80                                 func, arg);
81                         return BAD_VERBOSE;
82                 }
83         }
84
85         if (verbose < 0)
86                 printf("Print status every %d seconds\n", -verbose);
87         else if (verbose == 1)
88                 printf("Print status every operation\n");
89         else if (verbose > 1)
90                 printf("Print status every %d operations\n", verbose);
91
92         return verbose;
93 }
94
95 int main(int argc, char *argv[])
96 {
97         char filename[1024];
98         int verbose = 0;
99         unsigned long count, i;
100         int threads = 0;
101         char *end;
102         int rc = 0;
103
104         if (argc < 3 || argc > 5) {
105                 fprintf(stderr,
106                         "usage: %s <filename> <count> [verbose [threads]]\n",
107                         argv[0]);
108                 exit(1);
109         }
110
111         count = strtoul(argv[2], &end, 0);
112         if (*end) {
113                 fprintf(stderr, "%s: error: bad iteration count '%s'\n",
114                         argv[0], argv[1]);
115                 exit(2);
116         }
117         if (argc == 4) {
118                 verbose = get_verbose(argv[0], argv[3]);
119                 if (verbose == BAD_VERBOSE)
120                         exit(2);
121         }
122         if (argc == 5) {
123                 threads = strtoul(argv[4], &end, 0);
124                 if (*end) {
125                         fprintf(stderr, "%s: error: bad thread count '%s'\n",
126                                 argv[0], argv[1]);
127                         exit(2);
128                 }
129         }
130
131         for (i = 1; i <= threads; i++) {
132                 rc = fork();
133                 if (rc < 0) {
134                         fprintf(stderr, "%s: error: #%ld - %s\n",
135                                 cmdname(argv[0]), i, strerror(rc = errno));
136                         break;
137                 } else if (rc == 0) {
138                         thread = i;
139                         break;
140                 } else
141                         printf("%s: thread #%ld (PID %d) started\n",
142                                cmdname(argv[0]), i, rc);
143                 rc = 0;
144         }
145
146         if (threads && thread == 0) {   /* parent process */
147                 int live_threads = threads;
148
149                 while (live_threads > 0) {
150                         int status;
151                         pid_t ret;
152
153                         ret = waitpid(0, &status, 0);
154                         if (ret == 0) {
155                                 continue;
156                         }
157
158                         if (ret < 0) {
159                                 fprintf(stderr, "%s: error: wait - %s\n",
160                                         argv[0], strerror(errno));
161                                 if (!rc)
162                                         rc = errno;
163                         } else {
164                                 /*
165                                  * This is a hack.  We _should_ be able to use
166                                  * WIFEXITED(status) to see if there was an
167                                  * error, but it appears to be broken and it
168                                  * always returns 1 (OK).  See wait(2).
169                                  */
170                                 int err = WEXITSTATUS(status);
171                                 if (err || WIFSIGNALED(status))
172                                         fprintf(stderr,
173                                                 "%s: error: PID %d had rc=%d\n",
174                                                 argv[0], ret, err);
175                                 if (!rc)
176                                         rc = err;
177
178                                 live_threads--;
179                         }
180                 }
181         } else {
182                 struct timeval start, end, next_time;
183                 unsigned long next_count;
184                 double diff;
185
186                 gettimeofday(&start, NULL);
187                 next_time.tv_sec = start.tv_sec - verbose;
188                 next_time.tv_usec = start.tv_usec;
189
190                 for (i = 0, next_count = verbose; i < count; i++) {
191                         if (threads)
192                                 sprintf(filename, "%s-%d-%ld",
193                                         argv[1], thread, i);
194                         else
195                                 sprintf(filename, "%s-%ld", argv[1], i);
196
197                         rc = mknod(filename, S_IFREG, 0);
198                         if (rc < 0) {
199                                 fprintf(stderr, "%s: error: mknod(%s): %s\n",
200                                         cmdname(argv[0]), filename,
201                                         strerror(errno));
202                                 rc = errno;
203                                 break;
204                         }
205                         if (unlink(filename) < 0) {
206                                 fprintf(stderr, "%s: error: unlink(%s): %s\n",
207                                         cmdname(argv[0]), filename,
208                                         strerror(errno));
209                                 rc = errno;
210                                 break;
211                         }
212                         if (be_verbose(verbose, &next_time,i,&next_count,count))
213                                 printf("%s: number %ld\n", cmdname(argv[0]), i);
214                 }
215
216                 gettimeofday(&end, NULL);
217                 diff = difftime(&end, &start);
218
219                 printf("%s: %ldx2 files in %.4gs (%.4g ops/s): rc = %d: %s",
220                        cmdname(argv[0]), i, diff, (double)i * 2 / diff,
221                        rc, ctime(&end.tv_sec));
222         }
223         return rc;
224 }