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