Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / tests / multiop.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  */
4 #ifndef _GNU_SOURCE
5 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
6 #endif
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mman.h>
14 #include <signal.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <lustre/liblustreapi.h>
18
19 #define T1 "write data before unlink\n"
20 #define T2 "write data after unlink\n"
21 char msg[] = "yabba dabba doo, I'm coming for you, I live in a shoe, I don't know what to do.\n'Bigger, bigger,and bigger yet!' cried the Creator.  'You are not yet substantial enough for my boundless intents!'  And ever greater and greater the object became, until all was lost 'neath its momentus bulk.\n";
22 char *buf, *buf_align;
23 int bufsize = 0;
24 #define ALIGN 65535
25
26 char usage[] = 
27 "Usage: %s filename command-sequence\n"
28 "    command-sequence items:\n"
29 "        c  close\n"
30 "        C[num] create with optional stripes\n"
31 "        d  mkdir\n"
32 "        D  open(O_DIRECTORY)\n"
33 "        L  link\n"
34 "        l  symlink\n"
35 "        m  mknod\n"
36 "        M  rw mmap to EOF (must open and stat prior)\n"
37 "        N  rename\n"
38 "        o  open(O_RDONLY)\n"
39 "        O  open(O_CREAT|O_RDWR)\n"
40 "        r[num] read [optional length]\n"
41 "        R  reference entire mmap-ed region\n"
42 "        s  stat\n"
43 "        S  fstat\n"
44 "        t  fchmod\n"
45 "        T[num] ftruncate [optional position, default 0]\n"
46 "        u  unlink\n"
47 "        U  munmap\n"
48 "        w[num] write optional length\n"
49 "        W  write entire mmap-ed region\n"
50 "        y  fsync\n"
51 "        Y  fdatasync\n"
52 "        z[num] seek [optional position, default 0]\n"
53 "        _  wait for signal\n";
54
55 static int usr1_received;
56 void usr1_handler(int unused)
57 {
58         usr1_received = 1;
59 }
60
61 static const char *
62 pop_arg(int argc, char *argv[])
63 {
64         static int cur_arg = 3;
65
66         if (cur_arg >= argc)
67                 return NULL;
68
69         return argv[cur_arg++];
70 }
71
72 struct flag_mapping {
73        const char *string;
74        const int  flag;
75 } flag_table[] = {
76        {"O_RDONLY", O_RDONLY},
77        {"O_WRONLY", O_WRONLY},
78        {"O_RDWR", O_RDWR},
79        {"O_CREAT", O_CREAT},
80        {"O_EXCL", O_EXCL},
81        {"O_NOCTTY", O_NOCTTY},
82        {"O_TRUNC", O_TRUNC},
83        {"O_APPEND", O_APPEND},
84        {"O_NONBLOCK", O_NONBLOCK},
85        {"O_NDELAY", O_NDELAY},
86        {"O_SYNC", O_SYNC},
87 #ifdef O_DIRECT
88        {"O_DIRECT", O_DIRECT},
89 #endif
90        {"O_LARGEFILE", O_LARGEFILE},
91        {"O_DIRECTORY", O_DIRECTORY},
92        {"O_NOFOLLOW", O_NOFOLLOW},
93        {"", -1}
94 };
95
96 int get_flags(char *data, int *rflags)
97 {
98         char *cloned_flags;
99         char *tmp;
100         int flag_set = 0;
101         int flags = 0;
102         int size = 0;
103
104         cloned_flags = strdup(data);
105         if (cloned_flags == NULL) {
106                 fprintf(stderr, "Insufficient memory.\n");
107                 exit(-1);
108         }
109
110         for (tmp = strtok(cloned_flags, ":"); tmp;
111              tmp = strtok(NULL, ":")) {
112                 int i;
113
114                 size = tmp - cloned_flags;
115                 for (i = 0; flag_table[i].flag != -1; i++) {
116                         if (!strcmp(tmp, flag_table[i].string)){
117                                 flags |= flag_table[i].flag;
118                                 size += strlen(flag_table[i].string);
119                                 flag_set = 1;
120                                 break;
121                         }
122                 }
123         }
124         free(cloned_flags);
125
126         if (!flag_set) {
127                 *rflags = O_RDONLY;
128                 return 0;
129         }
130
131         *rflags = flags;
132         return size;
133 }
134
135 #define POP_ARG() (pop_arg(argc, argv))
136 #define min(a,b) ((a)>(b)?(b):(a))
137
138 int main(int argc, char **argv)
139 {
140         char *fname, *commands;
141         const char *newfile;
142         struct stat st;
143         size_t mmap_len = 0, i;
144         unsigned char *mmap_ptr = NULL, junk = 0;
145         int rc, len, fd = -1;
146         int flags;
147         int save_errno;
148         int verbose = 0;
149
150         if (argc < 3) {
151                 fprintf(stderr, usage, argv[0]);
152                 exit(1);
153         }
154
155         signal(SIGUSR1, usr1_handler);
156
157         fname = argv[1];
158
159         for (commands = argv[2]; *commands; commands++) {
160                 switch (*commands) {
161                 case '_':
162                         if (usr1_received == 0) {
163                                 if (verbose) {
164                                         printf("PAUSING\n");
165                                         fflush(stdout);
166                                 }
167                                 pause();
168                         }
169                         usr1_received = 0;
170                         signal(SIGUSR1, usr1_handler);
171                         break;
172                 case 'c':
173                         if (close(fd) == -1) {
174                                 save_errno = errno;
175                                 perror("close");
176                                 exit(save_errno);
177                         }
178                         fd = -1;
179                         break;
180                 case 'C':
181                         len = atoi(commands+1);
182                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
183                                              0, 0, len, 0);
184                         if (fd == -1) {
185                                 save_errno = errno;
186                                 perror("create stripe file");
187                                 exit(save_errno);
188                         }
189                         break;
190                 case 'd':
191                         if (mkdir(fname, 0755) == -1) {
192                                 save_errno = errno;
193                                 perror("mkdir(0755)");
194                                 exit(save_errno);
195                         }
196                         break;
197                 case 'D':
198                         fd = open(fname, O_DIRECTORY);
199                         if (fd == -1) {
200                                 save_errno = errno;
201                                 perror("open(O_DIRECTORY)");
202                                 exit(save_errno);
203                         }
204                         break;
205                 case 'l':
206                         newfile = POP_ARG();
207                         if (!newfile)
208                                 newfile = fname;
209                         if (symlink(fname, newfile)) {
210                                 save_errno = errno;
211                                 perror("symlink()");
212                                 exit(save_errno);
213                         }
214                         break;
215                 case 'L':
216                         newfile = POP_ARG();
217                         if (!newfile)
218                                 newfile = fname;
219                         if (link(fname, newfile)) {
220                                 save_errno = errno;
221                                 perror("symlink()");
222                                 exit(save_errno);
223                         }
224                         break;
225                 case 'm':
226                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
227                                 save_errno = errno;
228                                 perror("mknod(S_IFREG|0644, 0)");
229                                 exit(save_errno);
230                         }
231                         break;
232                 case 'M':
233                         mmap_len = st.st_size;
234                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
235                                         MAP_SHARED, fd, 0);
236                         if (mmap_ptr == MAP_FAILED) {
237                                 save_errno = errno;
238                                 perror("mmap");
239                                 exit(save_errno);
240                         }
241                         break;
242                 case 'N':
243                         newfile = POP_ARG();
244                         if (!newfile)
245                                 newfile = fname;
246                         if (rename (fname, newfile)) {
247                                 save_errno = errno;
248                                 perror("rename()");
249                                 exit(save_errno);
250                         }
251                         break;
252                 case 'O':
253                         fd = open(fname, O_CREAT|O_RDWR, 0644);
254                         if (fd == -1) {
255                                 save_errno = errno;
256                                 perror("open(O_RDWR|O_CREAT)");
257                                 exit(save_errno);
258                         }
259                         break;
260                 case 'o':
261                         len = get_flags(commands+1, &flags);
262                         commands += len;
263                         fd = open(fname, flags);
264                         if (fd == -1) {
265                                 save_errno = errno;
266                                 perror("open");
267                                 exit(save_errno);
268                         }
269                         break;
270                 case 'r':
271                         len = atoi(commands+1);
272                         if (len <= 0)
273                                 len = 1;
274                         if (bufsize < len) {
275                                 buf = realloc(buf, len + ALIGN);
276                                 if (buf == NULL) {
277                                         save_errno = errno;
278                                         perror("allocating buf for read\n");
279                                         exit(save_errno);
280                                 }
281                                 bufsize = len;
282                                 buf_align = (char *)((long)(buf + ALIGN) &
283                                                      ~ALIGN);
284                         }
285                         while (len > 0) {
286                                 rc = read(fd, buf_align, len);
287                                 if (rc == -1) {
288                                         save_errno = errno;
289                                         perror("read");
290                                         exit(save_errno);
291                                 }
292                                 if (rc < len)
293                                         fprintf(stderr, "short read: %u/%u\n",
294                                                 rc, len);
295                                 len -= rc;
296                         }
297                         break;
298                 case 'R':
299                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
300                                 junk += mmap_ptr[i];
301                         break;
302                 case 's':
303                         if (stat(fname, &st) == -1) {
304                                 save_errno = errno;
305                                 perror("stat");
306                                 exit(save_errno);
307                         }
308                         break;
309                 case 'S':
310                         if (fstat(fd, &st) == -1) {
311                                 save_errno = errno;
312                                 perror("fstat");
313                                 exit(save_errno);
314                         }
315                         break;
316                 case 't':
317                         if (fchmod(fd, 0) == -1) {
318                                 save_errno = errno;
319                                 perror("fchmod");
320                                 exit(save_errno);
321                         }
322                         break;
323                 case 'T':
324                         len = atoi(commands+1);
325                         if (ftruncate(fd, len) == -1) {
326                                 save_errno = errno;
327                                 printf("ftruncate (%d,%d)\n", fd, len);
328                                 perror("ftruncate");
329                                 exit(save_errno);
330                         }
331                         break;
332                 case 'u':
333                         if (unlink(fname) == -1) {
334                                 save_errno = errno;
335                                 perror("unlink");
336                                 exit(save_errno);
337                         }
338                         break;
339                 case 'U':
340                         if (munmap(mmap_ptr, mmap_len)) {
341                                 save_errno = errno;
342                                 perror("munmap");
343                                 exit(save_errno);
344                         }
345                         break;
346                 case 'v':
347                         verbose = 1;
348                         break;
349                 case 'w':
350                         len = atoi(commands+1);
351                         if (len <= 0)
352                                 len = 1;
353                         if (bufsize < len) {
354                                 buf = realloc(buf, len + ALIGN);
355                                 if (buf == NULL) {
356                                         save_errno = errno;
357                                         perror("allocating buf for write\n");
358                                         exit(save_errno);
359                                 }
360                                 bufsize = len;
361                                 buf_align = (char *)((long)(buf + ALIGN) &
362                                                      ~ALIGN);
363                                 strncpy(buf_align, msg, bufsize);
364                         }
365                         while (len > 0) {
366                                 rc = write(fd, buf_align, len);
367                                 if (rc == -1) {
368                                         save_errno = errno;
369                                         perror("write");
370                                         exit(save_errno);
371                                 }
372                                 if (rc < len)
373                                         fprintf(stderr, "short write: %u/%u\n",
374                                                 rc, len);
375                                 len -= rc;
376                         }
377                         break;
378                 case 'W':
379                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
380                                 mmap_ptr[i] += junk++;
381                         break;
382                 case 'y':
383                         if (fsync(fd) == -1) {
384                                 save_errno = errno;
385                                 perror("fsync");
386                                 exit(save_errno);
387                         }
388                         break;
389                 case 'Y':
390                         if (fdatasync(fd) == -1) {
391                                 save_errno = errno;
392                                 perror("fdatasync");
393                                 exit(save_errno);
394                         }
395                 case 'z':
396                         len = atoi(commands+1);
397                         if (lseek(fd, len, SEEK_SET) == -1) {
398                                 save_errno = errno;
399                                 perror("lseek");
400                                 exit(save_errno);
401                         }
402                         break;
403                 case '0':
404                 case '1':
405                 case '2':
406                 case '3':
407                 case '4':
408                 case '5':
409                 case '6':
410                 case '7':
411                 case '8':
412                 case '9':
413                         break;
414                 default:
415                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
416                         fprintf(stderr, usage, argv[0]);
417                         exit(1);
418                 }
419         }
420
421         if (buf)
422                 free(buf);
423
424         return 0;
425 }